package com.zmn.oms.third.dj58.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.zmn.base.common.data.common.dro.area.AreaDRO;
import com.zmn.base.common.data.dubbo.interfaces.area.AreaListRemoteService;
import com.zmn.base.product.common.dto.product.ec.ProductBaseDRO;
import com.zmn.base.product.dubbo.interfaces.channel.product.third.ChannelProductThirdListRemoteService;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.constant.StatusConsts;
import com.zmn.common.dictionary.GlobalDict;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.amount.AmountUtil;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.math.MoneyUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.reflect.BeanMapper;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.manager.redis.RedisManager;
import com.zmn.oms.business.interfaces.messageV1.app.MessageSendAppService;
import com.zmn.oms.business.interfaces.notifylog.OrderNotifyLogBService;
import com.zmn.oms.business.interfaces.third.Dj58ServicePriceItemService;
import com.zmn.oms.common.constant.*;
import com.zmn.oms.common.dto.ResultDTO;
import com.zmn.oms.common.enums.ChannelFacade;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.model.bo.order.OrderBO;
import com.zmn.oms.model.dto.order.proxy.*;
import com.zmn.oms.model.dto.product.OrderProductDTO;
import com.zmn.oms.model.dto.work.masterwork.CompleteDTO;
import com.zmn.oms.model.entity.notifylog.OrderNotifyLog;
import com.zmn.oms.model.entity.order.OrderExtend;
import com.zmn.oms.model.entity.remark.OrderRemark;
import com.zmn.oms.model.entity.remark.OrderRemarkDetail;
import com.zmn.oms.model.entity.serviceitem.OrderServiceItem;
import com.zmn.oms.model.entity.third.Dj58ServicePriceItem;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.model.entity.work.OrderWorkLogChange;
import com.zmn.oms.model.vo.work.ZsOrderWorkVO;
import com.zmn.oms.model.vo.work.modify.amount.ZsServiceItemVO;
import com.zmn.oms.services.interfaces.detail.OrderDetailService;
import com.zmn.oms.services.interfaces.order.OrderExtendService;
import com.zmn.oms.services.interfaces.remark.OrderRemarkDetailService;
import com.zmn.oms.services.interfaces.remark.OrderRemarkService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import com.zmn.oms.third.base.util.ThirdOrderUtil;
import com.zmn.oms.third.core.tracker.FacadeTracker;
import com.zmn.oms.third.dj58.DaoJia58Consts;
import com.zmn.oms.third.dj58.DaoJia58Mapper;
import com.zmn.oms.third.dj58.dto.*;
import com.zmn.oms.third.dj58.dto.api.*;
import com.zmn.oms.third.dj58.service.DaoJia58Service;
import com.zmn.oms.third.dj58.service.VasOrderBService;
import com.zmn.oms.third.dj58.util.DaoJia58Util;
import com.zmn.oms.zmn.business.interfaces.proxy.ProxyOrderBService;
import com.zmn.oms.zmn.business.interfaces.work.ZsOrderWorkQueryBService;
import com.zmn.oms.zmn.business.interfaces.work.autoflow.WorkFlowContextBService;
import com.zmn.oms.zmn.business.interfaces.work.masterwork.ZsMasterWorkBService;
import com.zmn.oms.zmn.normal.business.interfaces.serviceitem.ZsNormalOrderServiceItemBService;
import com.zmn.pay.common.constant.PayConsts;
import com.zmn.vas.common.dro.order.OrderDRO;
import com.zmn.vas.dubbo.consts.VasDubboConsts;
import com.zmn.vas.dubbo.interfaces.order.VasOrderListRemoteService;
import com.zmn.vas.dubbo.interfaces.order.VasOrderModifyRemoteService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 类描述：58到家直约服务接口调用实现类
 *
 * @author XieWenBing
 * @date 2019/11/01 13:08
 */
@Service
@Slf4j
public class DaoJia58ServiceImpl implements DaoJia58Service {
    @Resource
    private RedisManager redisManager;

    @Autowired
    private ProxyOrderBService proxyOrderBService;

    @Autowired
    private WorkFlowContextBService workFlowContextBService;

    @Autowired
    protected ZsOrderWorkQueryBService zsOrderWorkQueryBService;

    @Autowired
    protected ZsNormalOrderServiceItemBService zsNormalOrderServiceItemBService;

    @Autowired
    protected OrderWorkService orderWorkService;

    @Autowired
    protected MessageSendAppService messageSendAppService;

    @Autowired
    protected Dj58ServicePriceItemService dj58ServicePriceItemService;

    @Autowired
    private OrderExtendService orderExtendService;

    @Autowired
    private OrderNotifyLogBService orderNotifyLogBService;

    @Autowired
    private OrderRemarkService orderRemarkService;

    @Autowired
    private OrderRemarkDetailService orderRemarkDetailService;

    @Autowired
    private OrderDetailService orderDetailService;
    @Autowired
    private VasOrderBService vasOrderBService;

    @Autowired
    private ZsMasterWorkBService zsMasterWorkBService;

    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    protected AreaListRemoteService areaListRemoteService;

    @Reference(version = VasDubboConsts.INTERFACE_VERSION, check = false)
    private VasOrderModifyRemoteService vasOrderModifyRemoteService;

    @Reference(version = VasDubboConsts.INTERFACE_VERSION, check = false)
    private VasOrderListRemoteService vasOrderListRemoteService;

    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    protected ChannelProductThirdListRemoteService channelProductThirdListRemoteService;

    /**
     * 处理58到家发送的订单消息（创建线索，补充支付，取消订单，订单完成，订单金额变更等）
     * @param msg
     * @return Dj58Result
     * @author xiewenbing
     */
    @Override
    public DaoJia58Response onMessage(String msg) {
        FacadeTracker.FacadeTrackerCore tracker = FacadeTracker.getTracker()
                .dataIn(ChannelFacade.DAOJIA_58)
                .reqSummary(msg);

        DaoJia58Response daoJia58Response = null;
        try {
            daoJia58Response = this.handleSyncOrderMsg(msg);
        } catch (OmsBaseException oe) {
            log.error(String.format("【%s】处理订单出现异常: %s", DaoJia58Consts.CHANNEL_NAME, oe.getMessage()), oe);

            tracker.error(oe, oe.getMessage());

            // 发生异常或错误
            daoJia58Response = new DaoJia58Response();
            daoJia58Response.setCode(oe.getCode());
            daoJia58Response.setMessage(oe.getMessage());
            daoJia58Response.setData(null);
        } catch (Exception e) {
            log.error(String.format("【%s】处理订单出现异常: %s", DaoJia58Consts.CHANNEL_NAME, e.getMessage()), e);

            tracker.error(e, e.getMessage());

            // 发生异常或错误
            daoJia58Response = new DaoJia58Response();
            daoJia58Response.setCode(2);
            daoJia58Response.setMessage(e.getMessage());
            daoJia58Response.setData(null);
        }

        tracker.respSummary(JSON.toJSONString(daoJia58Response))
                .success(daoJia58Response.getCode() == 0)
                .commit();

        return daoJia58Response;
    }

    /**
     * 处理58到家发送的订单消息（创建线索，补充支付，取消订单，订单完成，订单金额变更等）
     *
     * @param paramOrderMsg
     * @return Dj58Result
     * @author xiewenbing
     */
    private DaoJia58Response handleSyncOrderMsg(String paramOrderMsg) throws OmsBaseException {
        DaoJia58ReceiveRequest daoJia58ReceiveRequest = JSON.parseObject(paramOrderMsg, DaoJia58ReceiveRequest.class);
        if (Objects.isNull(daoJia58ReceiveRequest)){
            throw new OmsBaseException(DaoJia58Consts.ZMN_RETURN_CODE_PARAM_ERROR,"参数验证失败");
        }
        DaoJia58Response daoJia58Response = new DaoJia58Response();
        daoJia58Response.setCode(DaoJia58Consts.ZMN_RETURN_CODE_SUCCESS);
        daoJia58Response.setMessage("success");
        daoJia58Response.setData("");

        // 根据不同请求进行处理
        switch (daoJia58ReceiveRequest.getFunId()) {
            case DaoJia58Consts.CREATE_CLUE_REQUST_FLAG:
                this.parseCreateClueRequest(daoJia58Response, daoJia58ReceiveRequest.getDaojiaJson());
                break;
            case DaoJia58Consts.CANCEL_ORDER_REQUEST_FLAG:
                this.parseCancelOrderRequest(daoJia58Response, daoJia58ReceiveRequest.getDaojiaJson());
                break;
            case DaoJia58Consts.REPLENISH_PAY_NOTIFY_FLAG:
                this.parseReplenishPayNotify(daoJia58Response, daoJia58ReceiveRequest.getDaojiaJson());
                break;
            case DaoJia58Consts.BILL_CHANGE_REQUEST_FLAG:
                this.parseBillChangeRequest(daoJia58Response, daoJia58ReceiveRequest.getDaojiaJson());
                break;
            case DaoJia58Consts.FINISH_ORDER_REQUEST_FLAG:
                this.parseOrderFinishRequest(daoJia58Response, daoJia58ReceiveRequest.getDaojiaJson());
                break;
            case DaoJia58Consts.INSURE_CREATE_FLAG:
                // 创建保单
                this.parseInsureCreateRequest(daoJia58Response, daoJia58ReceiveRequest.getDaojiaJson());
                break;
            case DaoJia58Consts.INSURE_CANCEL_FLAG:
                // 取消保单服务
                this.parseInsureCancelRequest(daoJia58Response, daoJia58ReceiveRequest.getDaojiaJson());
                break;
            case DaoJia58Consts.INSURE_APPLY_REPAIR_FLAG:
                // 申请维修服务
                this.parseInsureApplyRepairRequest(daoJia58Response, daoJia58ReceiveRequest.getDaojiaJson());
                break;
            default:
                throw new OmsBaseException(DaoJia58Consts.ZMN_RETURN_CODE_PARAM_ERROR, "参数错误");
        }

        return daoJia58Response;
    }

    /**
     * 申请保单服务
     *
     * @param daoJia58Response
     * @param daojiaJson
     */
    private void parseInsureApplyRepairRequest(DaoJia58Response daoJia58Response, String daojiaJson) throws OmsBaseException {
        FacadeTracker.FacadeTrackerCore tracker = FacadeTracker.getTracker().remark("收到申请保单服务消息");

        log.info("#oms#insureApplyRepairRequest data:[{}]", daojiaJson);
        DaoJia58CreateReworkOrderParam reworkOrder = JSON.parseObject(daojiaJson, DaoJia58CreateReworkOrderParam.class);
        if (Objects.isNull(reworkOrder) || Objects.isNull(reworkOrder.getInsureId()) || Objects.isNull(reworkOrder.getOrderId())) {
            throw new OmsBaseException(DaoJia58Consts.ZMN_RETURN_CODE_PARAM_ERROR, "解析参数失败");
        }

        // serviceKey判断
        String serviceKey = String.valueOf(reworkOrder.getServiceKey());
        if (serviceKey.compareToIgnoreCase(DaoJia58Consts.APPKEY) != 0) {
            throw new OmsBaseException(DaoJia58Consts.ZMN_RETURN_CODE_PARAM_ERROR, "参数错误-ServiceKey不匹配");
        }

        log.debug("查询增值信息-Request：MemOrderId=[{}]", reworkOrder.getInsureId());
        ResponseDTO<OrderDRO> vasResponseDTO = vasOrderListRemoteService.getEffectiveOrderByOrderId(Long.parseLong(reworkOrder.getInsureId()));
        log.debug("查询增值信息-Response：ResponseDTO=[{}]", JSON.toJSONString(vasResponseDTO));

        if (!vasResponseDTO.isSuccess()) {
            log.error("【{}】增值id查询失败-增值单号:[{}]", DaoJia58Consts.CHANNEL_ID_DJ58_REWORK ,reworkOrder.getInsureId());
            throw new OmsBaseException(DaoJia58Consts.ZMN_RETURN_CODE_PARAM_ERROR, "增值id查询失败，未找到此增值单");
        }

        CreateOrderDTO createOrderDTO = this.parseCreateReworkOrder(vasResponseDTO.getData().getMobile(), reworkOrder);

        if (createOrderDTO != null) {
            boolean unknowAddress = createOrderDTO.getCityId() == null;
            boolean unknowProduct = Objects.equals(OrderConsts.CHANNEL_DISABLED_PRODUCT_ID,
                    createOrderDTO.getOrderProductList().get(0).getProductId());
            // 地址解析失败/产品解析失败时，默认地址写重庆，产品设置为其他，避免自动派单
            if (unknowAddress || unknowProduct) {
                ThirdOrderUtil.fillDefaultOrderInfo(createOrderDTO, "；产品未能自动识别，需人工确认");
            }
        }

        try {
            // 保存订单
            OrderBO orderBO = proxyOrderBService.createOrder(createOrderDTO);
            OrderWork orderWork = orderBO.getOrderWork();
            Long orderId = orderWork.getOrderId();

            tracker.orderId(orderId);
            log.info("【{}】保存订单成功 OrderId:[{}]", "58到家", orderId);

            // 工单自动流转
            workFlowContextBService.asyncAutoFlow(orderId,orderWork.getWorkId());

            daoJia58Response.setData(orderWork.getOrderId().toString());
        } catch (Exception e) {
            log.error("【58到家】创建订单失败：{}", e.getMessage(), e);
            daoJia58Response.setCode(StatusConsts.ERROR_UNKNOWN);
            daoJia58Response.setMessage(e.getMessage());
        }

    }

    /**
     * 取消保单服务
     *
     * @param daoJia58Response
     * @param daojiaJson
     */
    private void parseInsureCancelRequest(DaoJia58Response daoJia58Response, String daojiaJson) {
        FacadeTracker.getTracker().remark("收到取消保单服务消息");

        JSONObject data = JSON.parseObject(daojiaJson);
        vasOrderBService.cancelInsure(daoJia58Response,data);
    }

    /**
     * 创建保单服务
     *
     * @param daoJia58Response
     * @param daojiaJson
     */
    private void parseInsureCreateRequest(DaoJia58Response daoJia58Response, String daojiaJson) throws OmsBaseException {
        FacadeTracker.getTracker().remark("收到新增保单消息");
        log.info("#oms#parseInsureCreateRequest daojiaJson : {}", daojiaJson);
        vasOrderBService.createInsure(daoJia58Response,daojiaJson);
    }

    /**
     * 解析并验证58到家的请求数据
     *
     * @param paramRequest
     * @return DaoJia58ReceiveRequest
     * @author xiewenbing
     */
    protected DaoJia58ReceiveRequest parseAndVerifyRequestParam(String paramRequest) {
        if (Objects.isNull(paramRequest) || paramRequest.isEmpty()) {
            return null;
        }

        DaoJia58ReceiveRequest daoJia58ReceiveRequest = JSON.parseObject(paramRequest, DaoJia58ReceiveRequest.class);
        if (null == daoJia58ReceiveRequest) {
            return null;
        }

        // 验证签名
        if (!DaoJia58Util.verifyRequestSign(daoJia58ReceiveRequest.getDaojiaSign(), daoJia58ReceiveRequest.getNonce(),
                daoJia58ReceiveRequest.getTimestamp())) {
            return null;
        }

        // 判断数据是否为空
        String jsonData = daoJia58ReceiveRequest.getDaojiaJson();
        if (Objects.isNull(jsonData) || jsonData.isEmpty()) {
            return null;
        }

        return daoJia58ReceiveRequest;
    }

    /**
     * 处理58到家创建线索的请求
     *
     * @param daoJia58Response
     * @param dataRequest
     * @return
     * @author xiewenbing
     */
    protected void parseCreateClueRequest(DaoJia58Response daoJia58Response, String dataRequest) throws OmsBaseException {
        FacadeTracker.FacadeTrackerCore tracker = FacadeTracker.getTracker().remark("收到新增订单消息");

        // 参数判断
        if (Objects.isNull(dataRequest) || dataRequest.isEmpty()) {
            throw new OmsBaseException(DaoJia58Consts.ZMN_RETURN_CODE_PARAM_ERROR, "参数不正确-daojiaJson为空");
        }

        // 获取创建线索的具体内容
        DaoJia58CreateClueParam paramCreateClue = JSON.parseObject(dataRequest, DaoJia58CreateClueParam.class);
        if (Objects.isNull(paramCreateClue)) {
            throw new OmsBaseException(DaoJia58Consts.ZMN_RETURN_CODE_PARAM_ERROR, "解析参数失败");
        }

        // serviceKey判断
        String serviceKey = String.valueOf(paramCreateClue.getServiceKey());
        if (serviceKey.compareToIgnoreCase(DaoJia58Consts.APPKEY) != 0) {
            throw new OmsBaseException(DaoJia58Consts.ZMN_RETURN_CODE_PARAM_ERROR, "参数错误-ServiceKey不匹配");
        }

        // 判断是否有对应的产品信息
        if (Objects.isNull(this.parseProductMapByDj58CreateClueParam(paramCreateClue))) {
            throw new OmsBaseException(DaoJia58Consts.ZMN_RETURN_CODE_PARAM_ERROR, "参数错误-暂不提供对应的服务");
        }

        // 生成创建订单的数据
        CreateOrderDTO createOrderDTO = this.makeZmnCreateOrderData(paramCreateClue);
        if (Objects.isNull(createOrderDTO)) {
            throw new OmsBaseException(DaoJia58Consts.ZMN_RETURN_CODE_PARAM_ERROR, "重复的订单数据");
        }

        try {
            OrderBO orderBO = proxyOrderBService.createOrder(createOrderDTO);
            Long orderId = orderBO.getOrder().getOrderId();
            this.saveSyncAcceptOrderClueId(orderId,paramCreateClue.getClueId(),paramCreateClue.getOrgId());

            tracker.orderId(orderId);
            log.info("【{}】保存订单成功 OrderId:[{}]", DaoJia58Consts.CHANNEL_NAME, orderId);
        } catch (Exception exception) {
            log.error("【{}】保存订单失败 消息:[{}]", DaoJia58Consts.CHANNEL_NAME, exception.getMessage());
            throw new OmsBaseException(DaoJia58Consts.ZMN_RETURN_CODE_SERVER_ERROR, "创建订单失败");
        }

        // 工单自动流转  -- xiewenbing 2020-05-29 改为接单后自动流转
        // OrderWork orderWork = orderBO.getOrderWork();
        // workFlowContextBService.asyncAutoFlow(orderWork.getOrderId(), orderWork.getWorkId());
    }

    /**
     * 处理58到家取消订单的请求
     *
     * @param daoJia58Response
     * @param dataRequest
     * @return
     * @author xiewenbing
     */
    protected void parseCancelOrderRequest(DaoJia58Response daoJia58Response, String dataRequest) throws OmsBaseException {
        FacadeTracker.FacadeTrackerCore tracker = FacadeTracker.getTracker().remark("收到取消订单消息");

        // 参数判断
        if (Objects.isNull(dataRequest) || dataRequest.isEmpty()) {
            throw new OmsBaseException(DaoJia58Consts.ZMN_RETURN_CODE_PARAM_ERROR, "参数不正确-daojiaJson为空");
        }

        // 获取取消订单的具体内容
        DaoJia58CancelOrderParam paramCancelOrder = JSON.parseObject(dataRequest, DaoJia58CancelOrderParam.class);
        if (Objects.isNull(paramCancelOrder)) {
            throw new OmsBaseException(DaoJia58Consts.ZMN_RETURN_CODE_PARAM_ERROR, "解析参数失败");
        }

        // serviceKey判断
        String serviceKey = String.valueOf(paramCancelOrder.getServiceKey());
        if (serviceKey.compareToIgnoreCase(DaoJia58Consts.APPKEY) != 0) {
            throw new OmsBaseException(DaoJia58Consts.ZMN_RETURN_CODE_PARAM_ERROR, "参数错误-ServiceKey不匹配");
        }

        // 查找对应的订单
        String outerId = String.valueOf(paramCancelOrder.getOrderId());
        ZsOrderWorkVO orderWorkVO = zsOrderWorkQueryBService.findOrderWorkByOuterIdAndChannelIds(outerId,
                DaoJia58Consts.getAllChannelIds());
        if (Objects.isNull(orderWorkVO)) {
            throw new OmsBaseException(DaoJia58Consts.ZMN_RETURN_CODE_PARAM_ERROR,
                    String.format("找不到对应的订单 58到家OuterId=[%s]", outerId));
        }

        tracker.orderId(orderWorkVO.getOrderId());

        DaoJia58Consts.ChannelInfo channelInfo = DaoJia58Consts.getChannelInfo(orderWorkVO.getChannelId(), null);

        log.info("【{}】取消订单：订单Id:[{}]，OuterId:[{}]，取消类型:[{}]，取消原因:[{}]", channelInfo.getName(),
                orderWorkVO.getOrderId(), outerId, paramCancelOrder.getCancelType(), paramCancelOrder.getCancelReason());

        // 取消订单
        CancelOrderDTO cancelOrderDTO = new CancelOrderDTO();
        cancelOrderDTO.setOrderId(orderWorkVO.getOrderId());
        cancelOrderDTO.setOuterId(outerId);
        cancelOrderDTO.setChannelId(channelInfo.getId());
        cancelOrderDTO.setOperatorId((long) channelInfo.getId());
        cancelOrderDTO.setOperatorType(GlobalConsts.OPERATE_USER_TYPE_CHANNEL);

        String cancelReason = paramCancelOrder.getCancelReason();
        if (Objects.isNull(cancelReason) || cancelReason.isEmpty()) {
            cancelReason = DaoJia58Mapper.getCancelOrderReason(paramCancelOrder.getCancelType());
        }

        try {
            cancelOrderDTO.setRemark(cancelReason);
            proxyOrderBService.cancelOrder(cancelOrderDTO);
        } catch (OmsBaseException omsBaseException) {
            log.error("【{}】取消订单失败 消息:[{}]", channelInfo.getName(), omsBaseException.getMessage());
            throw new OmsBaseException(DaoJia58Consts.ZMN_RETURN_CODE_SERVER_ERROR, "取消订单失败");
        }

    }

    /**
     * 处理58到家订单完成的请求
     *
     * @param daoJia58Response
     * @param dataRequest
     * @return
     * @author xiewenbing
     */
    protected void parseOrderFinishRequest(DaoJia58Response daoJia58Response, String dataRequest) throws OmsBaseException {
        FacadeTracker.FacadeTrackerCore tracker = FacadeTracker.getTracker()
                .remark("收到订单完成消息")
                .remark("已忽略该消息，不做处理");

        // 参数判断
        if (Objects.isNull(dataRequest) || dataRequest.isEmpty()) {
            throw new OmsBaseException(DaoJia58Consts.ZMN_RETURN_CODE_PARAM_ERROR, "参数不正确-daojiaJson为空");
        }

        // 获取订单完成的具体内容
        DaoJia58FinishOrderParam paramFinishOrder = JSON.parseObject(dataRequest, DaoJia58FinishOrderParam.class);
        if (Objects.isNull(paramFinishOrder)) {
            throw new OmsBaseException(DaoJia58Consts.ZMN_RETURN_CODE_PARAM_ERROR, "解析参数失败");
        }

        // serviceKey判断
        String serviceKey = String.valueOf(paramFinishOrder.getServiceKey());
        if (serviceKey.compareToIgnoreCase(DaoJia58Consts.APPKEY) != 0) {
            throw new OmsBaseException(DaoJia58Consts.ZMN_RETURN_CODE_PARAM_ERROR, "参数错误-ServiceKey不匹配");
        }

        // 订单完成的消息忽略 xiewenbing
        log.info("【{}-API】 收到订单完成的消息,外部订单id:[{}]，完成时间:[{}]", DaoJia58Consts.CHANNEL_NAME, paramFinishOrder.getOrderId(),
                paramFinishOrder.getRealFinishTime());

        // 更新订单金额信息  xiewenbing
        String outerId = String.valueOf(paramFinishOrder.getOrderId());
        ZsOrderWorkVO orderWorkVO = zsOrderWorkQueryBService.findOrderWorkByOuterIdAndChannelIds(outerId,
                DaoJia58Consts.getAllChannelIds());

        if (Objects.isNull(orderWorkVO)) {
            tracker.remark("未找到对应的订单，outerId=[%s]", outerId);
            return;
        }
        tracker.orderId(orderWorkVO.getOrderId());

        // 添加系统日志--2020/087/17 xiewenbing
        OrderLogDTO orderLogDTO = new OrderLogDTO();
        orderLogDTO.setOrderId(orderWorkVO.getOrderId());
        orderLogDTO.setOuterId(orderWorkVO.getOuterId());
        orderLogDTO.setChannelId(orderWorkVO.getChannelId());
        orderLogDTO.setOperatorId((long)orderWorkVO.getChannelId());
        orderLogDTO.setOperatorType(GlobalConsts.OPERATE_USER_TYPE_SYSTEM);
        orderLogDTO.setOperator("系统");
        orderLogDTO.setType(OrderLogConsts.ORDER_LOG_TYPE_CHANNEL_REMARK);
        orderLogDTO.setOperatorLogRemark("渠道完成");

        proxyOrderBService.addOrderLog(orderLogDTO);

    }

    /**
     * 处理58到家补充支付成功的通知
     *
     * @param daoJia58Response
     * @param dataRequest
     * @return
     * @author xiewenbing
     */
    protected void parseReplenishPayNotify(DaoJia58Response daoJia58Response, String dataRequest) throws OmsBaseException {
        FacadeTracker.FacadeTrackerCore tracker = FacadeTracker.getTracker()
                .remark("收到补充支付通知消息")
                .remark("已忽略该消息，不做处理");

        // 参数判断
        if (Objects.isNull(dataRequest) || dataRequest.isEmpty()) {
            throw new OmsBaseException(DaoJia58Consts.ZMN_RETURN_CODE_PARAM_ERROR, "参数不正确-daojiaJson为空");
        }

        // 获取补充支付信息的具体内容
        DaoJia58ReplenishPayParam paramReplenishPay = JSON.parseObject(dataRequest, DaoJia58ReplenishPayParam.class);
        if (Objects.isNull(paramReplenishPay)) {
            throw new OmsBaseException(DaoJia58Consts.ZMN_RETURN_CODE_PARAM_ERROR, "解析参数失败");
        }

        // serviceKey判断
        String serviceKey = String.valueOf(paramReplenishPay.getServiceKey());
        if (serviceKey.compareToIgnoreCase(DaoJia58Consts.APPKEY) != 0) {
            throw new OmsBaseException(DaoJia58Consts.ZMN_RETURN_CODE_PARAM_ERROR, "参数错误-ServiceKey不匹配");
        }

        String outerId = String.valueOf(paramReplenishPay.getOrderId());

        // 打印信息 ...... xiewenbing
        log.info("【{}-API】 收到补充支付的消息,外部订单id:[{}]，完成时间:[{}]", DaoJia58Consts.CHANNEL_NAME, outerId);

        ZsOrderWorkVO orderWorkVO = zsOrderWorkQueryBService.findOrderWorkByOuterIdAndChannelIds(outerId,
                DaoJia58Consts.getAllChannelIds());
        if (orderWorkVO != null) {
            tracker.orderId(orderWorkVO.getOrderId());
        }

    }

    /**
     * 处理58到家订单金额发生改变的通知
     *
     * @param daoJia58Response
     * @param dataRequest
     * @return
     * @author xiewenbing
     */
    protected void parseBillChangeRequest(DaoJia58Response daoJia58Response, String dataRequest) throws OmsBaseException {
        FacadeTracker.FacadeTrackerCore tracker = FacadeTracker.getTracker().remark("收到订单金额变更消息");

        // 参数判断
        if (Objects.isNull(dataRequest) || dataRequest.isEmpty()) {
            throw new OmsBaseException(DaoJia58Consts.ZMN_RETURN_CODE_PARAM_ERROR, "参数不正确-daojiaJson为空");
        }

        // 获取创建线索的具体内容
        DaoJia58BillChangeParam paramBillChange = JSON.parseObject(dataRequest, DaoJia58BillChangeParam.class);
        if (Objects.isNull(paramBillChange)) {
            throw new OmsBaseException(DaoJia58Consts.ZMN_RETURN_CODE_PARAM_ERROR, "解析参数失败");
        }

        // serviceKey判断
        String serviceKey = String.valueOf(paramBillChange.getServiceKey());
        if (serviceKey.compareToIgnoreCase(DaoJia58Consts.APPKEY) != 0) {
            throw new OmsBaseException(DaoJia58Consts.ZMN_RETURN_CODE_PARAM_ERROR, "参数错误-ServiceKey不匹配");
        }

        // 更新订单金额信息  xiewenbing
        String outerId = String.valueOf(paramBillChange.getOrderId());
        ZsOrderWorkVO orderWorkVO = zsOrderWorkQueryBService.findOrderWorkByOuterIdAndChannelIds(outerId,
                DaoJia58Consts.getAllChannelIds());

        if (Objects.isNull(orderWorkVO)) {
            throw new OmsBaseException(DaoJia58Consts.ZMN_RETURN_CODE_PARAM_ERROR,String.format("找不到对应的订单数据 58到家OuterId=[%s]", outerId));
        }

        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderWorkVO.getOrderId(), orderWorkVO.getWorkId());
        if (Objects.isNull(orderWork)) {
            throw new OmsBaseException(DaoJia58Consts.ZMN_RETURN_CODE_PARAM_ERROR,String.format("找不到对应的订单: 58到家OuterId=[%s]", outerId));
        }

        tracker.orderId(orderWork.getOrderId());

        // 是否抵扣师傅收款额
        boolean subMasterAmount = true;
        if (Optional.ofNullable(orderWork.getMasterAmount()).orElse(0) <= 0) {
            // 不存在师傅收款额时（比如师傅上门报价前，用户在渠道方支付尾款），不抵扣师傅收款额，只记录渠道代收金额
            subMasterAmount = false;
        }

        DaoJia58Consts.ChannelInfo channelInfo = DaoJia58Consts.getChannelInfo(orderWork.getChannelId(), null);

        log.info("【{}-API】 收到订单金额发生改变的消息,外部订单id:[{}]，用户支付总金额:[{}],商家补贴总金额:[{}],结算金额:[{}],备注:[{}]，类型:[{}]",
                channelInfo.getName(), paramBillChange.getOrderId(), paramBillChange.getRealPrice(),
                paramBillChange.getCustomSubsidiesPrice(), paramBillChange.getStatementPrice(),
                paramBillChange.getRemark(), paramBillChange.getType());

        PayOrderDTO payOrderDTO = new PayOrderDTO();
        payOrderDTO.setChannelId(orderWork.getChannelId());
        payOrderDTO.setOrderId(orderWork.getOrderId());
        payOrderDTO.setWorkId(orderWork.getWorkId());
        payOrderDTO.setPayTime(new Date());
        payOrderDTO.setSubMasterAmount(subMasterAmount);

        // 转换为分,并且需减去原来的预付款，消息通知的金额为实际支付的所有金额
        Integer oldChannelPrepayAmount = Optional.ofNullable(orderWork.getChannelPrepayAmount()).orElse(0);
        Integer newChannelPrepayAmount = Double.valueOf(paramBillChange.getRealPrice() * 100).intValue();
        Integer realPayAmount = newChannelPrepayAmount - oldChannelPrepayAmount;

        StringBuilder remarkBuilder = new StringBuilder();
        switch (paramBillChange.getType()) {
            // 订单完成
            case DaoJia58Consts.BILL_CHANGE_TYPE_ORDER_FINISH:
                payOrderDTO.setPayAmount(realPayAmount);
                payOrderDTO.setOrderPayType(OrderConsts.API_ORDER_PAY_TYPE_CHANNEL_MASTER_AMOUNT);
                // 抵扣师傅收款额后，将订单置为完成状态，否则不更改订单状态
                payOrderDTO.setCompleteOrder(subMasterAmount);

                remarkBuilder.append("原预付金额：").append(MoneyUtil.parseToYuanStr(oldChannelPrepayAmount)).append("元，")
                        .append("补差金额：").append(MoneyUtil.parseToYuanStr(realPayAmount)).append("元；");

                // 没有二次支付， xiewenbing  2021/0/28
                if (realPayAmount <= 0 ) {
                    if (payOrderDTO.getCompleteOrder()) {
                        this.completeOrderNoSecondPay(orderWork, remarkBuilder.toString());
                    }

                    return;
                }

                if (subMasterAmount) {
                    // 发送push通知 Xiewenbing 2020.04.02
                    this.pushPayMessage(payOrderDTO);
                } else {
                    if (CollectionUtils.isEmpty(zsNormalOrderServiceItemBService.listByOrderId(orderWork.getOrderId()))) {
                        remarkBuilder.append("工单未选择服务项；");
                    }
                }

                break;
            // 订单支付
            case DaoJia58Consts.BILL_CHANGE_TYPE_ORDER_PAY:

                // 有订单收到此消息，修改为修改订单的渠道预付......xiewenbing 2020.01.14
                payOrderDTO.setPayAmount(newChannelPrepayAmount);
                payOrderDTO.setOrderPayType(OrderConsts.API_ORDER_PAY_TYPE_CHANNEL_PREPAID);
                payOrderDTO.setCompleteOrder(false);

                remarkBuilder.append("渠道预付款修改，原预付金额：")
                        .append(MoneyUtil.parseToYuanStr(oldChannelPrepayAmount)).append("元，")
                        .append("现预付金额：").append(MoneyUtil.parseToYuanStr(newChannelPrepayAmount)).append("元；");

                // 预付没有修改，仅记录日志  xiewenbing  2021/0/28
                if (realPayAmount <= 0) {
                    this.addLog(orderWork, remarkBuilder.toString());
                    return;
                }

                break;

            // 订单取消 和 订单退款
            case DaoJia58Consts.BILL_CHANGE_TYPE_ORDER_CANCEL:
            case DaoJia58Consts.BILL_CHANGE_TYPE_ORDER_REFUND:

                if (paramBillChange.getType() == DaoJia58Consts.BILL_CHANGE_TYPE_ORDER_CANCEL) {
                    log.info("【{}】变更订单金额 - 订单取消", channelInfo.getName());
                } else {
                    log.info("【{}】变更订单金额 - 订单退款", channelInfo.getName());
                }

                if (orderWork.getStatus() >= OrderStatusConsts.ORDER_STATUS_COMPLETE) {
                    throw new OmsBaseException(DaoJia58Consts.ZMN_RETURN_CODE_SERVER_ERROR, "订单已完成，无法进行金额变更");
                }

                // 订单为取消，不处理。 
                if (Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_FAIL)
                        || Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_DISCARD)) {

                    remarkBuilder.append("渠道预付款修改，原预付金额：")
                            .append(MoneyUtil.parseToYuanStr(oldChannelPrepayAmount)).append("元，")
                            .append("现预付金额：").append(MoneyUtil.parseToYuanStr(newChannelPrepayAmount))
                            .append("元，订单已取消，不修改");

                    this.addLog(orderWork, remarkBuilder.toString());
                    return;
                }

                payOrderDTO.setPayAmount(newChannelPrepayAmount);
                payOrderDTO.setOrderPayType(OrderConsts.API_ORDER_PAY_TYPE_CHANNEL_PREPAID);
                payOrderDTO.setCompleteOrder(false);
                break;
            default:
                throw new OmsBaseException(DaoJia58Consts.ZMN_RETURN_CODE_PARAM_ERROR, "错误的参数:变更类型未定义");
        }

        String logRemark = remarkBuilder.toString();

        tracker.remark(logRemark);

        payOrderDTO.setOperatorLogRemark(logRemark);
        payOrderDTO.setOperatorRemark(logRemark);
        try {
            proxyOrderBService.payOrder(payOrderDTO);
        } catch (Exception e) {
            log.error("【{}】更新订单金额失败：{}", channelInfo.getName(), e.getMessage());

            addLog(orderWork,String.format("渠道订单金额变更，原支付金额：%.2f，现支付金额：%.2f,总支付金额：%.2f，修改订单金额异常：%s",
                    oldChannelPrepayAmount.doubleValue()/100,
                    realPayAmount.doubleValue()/100,
                    newChannelPrepayAmount.doubleValue()/100,
                    e.getMessage()));

            throw new OmsBaseException(DaoJia58Consts.ZMN_RETURN_CODE_SERVER_ERROR, "更新订单金额失败");
        }
    }

    /**
     * 将订单设置为完成（没有二次支付）
     *
     * @param orderWork
     * @param logRemark
     */
    protected void completeOrderNoSecondPay(OrderWork orderWork, String logRemark) throws OmsBaseException{

        // 订单非进行中或者完成后，仅添加日志
        if (orderWork.getResultStatus() != OrderStatusConsts.WORK_RESULT_DOING
                || orderWork.getStatus() >= OrderStatusConsts.WORK_STATUS_COMPLETE) {

            this.addLog(orderWork, logRemark);
            return;
        }

        // 将工单状态置为成功
        CompleteDTO completeDTO = new CompleteDTO();
        completeDTO.setOrderId(orderWork.getOrderId());
        completeDTO.setWorkId(orderWork.getWorkId());
        completeDTO.setOperatorLogRemark(logRemark);
        zsMasterWorkBService.completeOrder(completeDTO);
    }

    /**
     * 创建维修单
     * @param mobile
     * @param reworkOrderParam
     * @return
     */
    protected CreateOrderDTO parseCreateReworkOrder(String mobile
            , DaoJia58CreateReworkOrderParam reworkOrderParam) throws OmsBaseException {

        String outerId = String.valueOf(reworkOrderParam.getOrderId());

        // 创建数据对象
        CreateOrderDTO createOrderDTO = new CreateOrderDTO();

        OrderWork dbOrderWork = null;
        {
            // 原订单属于58到家直约
            ZsOrderWorkVO orderWorkVO = zsOrderWorkQueryBService
                    .findOrderWorkByOuterIdAndChannelIds(outerId, DaoJia58Consts.getAllChannelIds());

            if (!Objects.isNull(orderWorkVO)) {
                dbOrderWork = orderWorkService.findOrderWorkByKey(orderWorkVO.getOrderId(), orderWorkVO.getWorkId());
            }

            if (Objects.isNull(dbOrderWork)) {
                log.error("【{}】查找不到对应的订单-订单号:[{}]", DaoJia58Consts.REWORK_CHANNEL_NAME , outerId);
                throw new OmsBaseException(DaoJia58Consts.ZMN_RETURN_CODE_PARAM_ERROR, "查找不到对应的订单");
            }
        }

        Long orderId = dbOrderWork.getOrderId();
        Long workId = dbOrderWork.getWorkId();

        _fillAddress(createOrderDTO, reworkOrderParam);

        // 产品
        OrderProductDTO orderProduct = new OrderProductDTO();
        orderProduct.setProductId(dbOrderWork.getProductId());
        orderProduct.setShowProductId(dbOrderWork.getShowProductId());
        orderProduct.setNumber(1);

        List<OrderProductDTO> orderProducts = new LinkedList<>();
        orderProducts.add(orderProduct);
        createOrderDTO.setOrderProductList(orderProducts);

        // 用户电话：使用会员电话作为第一联系电话，如当前电话与会员电话不同，将当前电话保存为第二联系电话
        createOrderDTO.setTelephone(mobile);
        if (!Objects.equals(mobile, reworkOrderParam.getPhone())) {
            createOrderDTO.setTelephone2(reworkOrderParam.getPhone());
        }

        // 原单号
        createOrderDTO.setOriginalId(null);   // 修改原工单为空，工单类型修改为新单  xiewenbing  2020/07/14
        createOrderDTO.setReworkId(orderId);
        createOrderDTO.setOuterId(outerId);
        createOrderDTO.setExtOuterData(reworkOrderParam.getInsureId());
        createOrderDTO.setOuterData(JSON.toJSONString(reworkOrderParam));

        createOrderDTO.setChannelId(DaoJia58Consts.CHANNEL_ID_DJ58_REWORK);
        createOrderDTO.setContactName(Optional.ofNullable(reworkOrderParam.getUserName()).orElse("58返修用户"));
        createOrderDTO.setRemark(reworkOrderParam.getContent());

        // expectDate 预约时间，注意就近转化为：整点和半点
        Date expectDate = reworkOrderParam.getApplyTime();
        if (Objects.nonNull(expectDate)) {
            SimpleDateFormat sdf = new SimpleDateFormat(DateUtil.FORMAT_DEFAULT);
            Date dutyTime = DateUtil.parse(sdf.format(expectDate), DateUtil.FORMAT_DATE);
            // 忽略掉当前时间超过预约时间的情况，由线下去确定预约时间
            if (dutyTime.getTime() > System.currentTimeMillis()) {
                createOrderDTO.setDutyTime(DateUtil.round(dutyTime, DateUtil.UNIT_MINUTE));
            }
        }

        createOrderDTO.setPlat(GlobalConsts.PLAT_MARK_ZMN);
        createOrderDTO.setGender(GlobalDict.GENDER_NO);
        createOrderDTO.setDisableDiscard(GlobalConsts.NO);
        createOrderDTO.setOperator("系统");
        createOrderDTO.setOperatorId((long) GlobalConsts.OPERATE_USER_TYPE_SYSTEM);
        createOrderDTO.setOperatorType(GlobalConsts.OPERATE_USER_TYPE_CHANNEL);
        createOrderDTO.setInputType(OrderConsts.ORDER_INPUT_TYPE_API);

        return createOrderDTO;
    }

    /**
     * 补全订单地址
     * @param zmnOrder
     * @param reworkOrderParam
     */
    private void _fillAddress(CreateOrderDTO zmnOrder, DaoJia58CreateReworkOrderParam reworkOrderParam) {
        String[] lngAndlat = reworkOrderParam.getLocation().split(",");
        String locationLng = lngAndlat[0];
        String locationLat = lngAndlat[1];

        // 具体地址放入address
        zmnOrder.setAddress(reworkOrderParam.getAddress());
        zmnOrder.setStreet(""); // street字段在数据库中不能为空

        // 获取cityId：如果有经纬度，以经纬度获取城市为准；
        if (locationLat != null && locationLng != null) {
            try {
                Double lng = Double.valueOf(locationLng);
                Double lat = Double.valueOf(locationLat);

                ResponseDTO<com.zmn.base.common.data.common.dro.area.AreaDRO> areaResponse = areaListRemoteService.getAreaByLatAndLng(lng, lat);
                com.zmn.base.common.data.common.dro.area.AreaDRO areaDRO = areaResponse.getData();

                if (areaDRO != null) {
                    zmnOrder.setCityId(areaDRO.getParentId());
                    zmnOrder.setLongitude(lng);
                    zmnOrder.setLatitude(lat);
                }
            } catch (Exception e) {
                log.error("【{}】使用经纬度获取CityId失败:[{}]。Longitude=[{}], Latitude=[{}]",
                        "58到家", e.getMessage(), locationLng,
                        locationLat, e);
            }
        }

        // 记录一下完整地址
        zmnOrder.setOperatorLogRemark(
                Optional.ofNullable(zmnOrder.getOperatorLogRemark()).orElse("") + "；地址：" + reworkOrderParam.getAddress());
    }

    /**
     * 转换58到家的创建线索为啄木鸟平台的创建订单数据对象
     *
     * @param daoJia58CreateClueParam
     * @return CreateOrderDTO
     * @auth XieWenBing
     */
    protected CreateOrderDTO makeZmnCreateOrderData(DaoJia58CreateClueParam daoJia58CreateClueParam) {

        // 获取线索id
        String clueId = String.valueOf(daoJia58CreateClueParam.getClueId());

        // 根据字段“type”去区分，“普通支付订单类型 ”归为“58到家直约”，“信用账户”归为“58同城公寓”
        DaoJia58Consts.ChannelInfo channelInfo = DaoJia58Consts.getChannelInfo(null, daoJia58CreateClueParam.getType());

        // 判断线索是否已经重复
        ZsOrderWorkVO zsOrderWorkVO = zsOrderWorkQueryBService.findOrderWorkByOuterIdAndChannelIds(
                clueId, DaoJia58Consts.getAllChannelIds());
        if (Objects.nonNull(zsOrderWorkVO)) {
            log.info("【{}-API】 重复的线索，线索id为:[{}]", channelInfo.getName(), clueId);
            return null;
        }

        // 创建数据对象
        CreateOrderDTO createOrderDTO = new CreateOrderDTO();

        // 设置外部数据
        DaoJia58OrderOuterData outerData = BeanMapper.map(daoJia58CreateClueParam, DaoJia58OrderOuterData.class);
        createOrderDTO.setOuterData(JSON.toJSONString(outerData));
        createOrderDTO.setExtOuterId(clueId);

        // 将同步数据中的订单关键信息记录进日志中
        Date validTime = new Date(daoJia58CreateClueParam.getValidTime());
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");

        createOrderDTO.setOperatorLogRemark(String.format(
                "订单线索：%s，服务项信息：%d-%s，订单总价：%.2f，实际价格：%.2f元，有效时间：%s；",
                clueId, daoJia58CreateClueParam.getServiceId(), daoJia58CreateClueParam.getServiceName(),
                daoJia58CreateClueParam.getTotalPrice(), daoJia58CreateClueParam.getRealPrice(),
                simpleDateFormat.format(validTime)));

        // 渠道id
        createOrderDTO.setChannelId(channelInfo.getId());

        // 联系人
        createOrderDTO.setContactName(daoJia58CreateClueParam.getUserName());

        // 电话.....判断如果没有电话，则填入一个临时电话 xiewenbing 2020-05-29
        String userMobile = daoJia58CreateClueParam.getUserMobile();
        if (StringUtil.isBlank(userMobile)) {
            userMobile = OrderConsts.CHANNEL_TEMP_MOBILE;
        }
        createOrderDTO.setTelephone(userMobile);

        // 地址
        createOrderDTO.setAddress(daoJia58CreateClueParam.getAddress());

        // 街道 - 暂时为空
        createOrderDTO.setStreet("");

        // 备注
        createOrderDTO.setRemark(daoJia58CreateClueParam.getRemark());

        // 平台标志
        createOrderDTO.setPlat(GlobalConsts.PLAT_MARK_ZMN);

        // 性别
        createOrderDTO.setGender(GlobalDict.GENDER_NO);

        // 是否允许弃单
        createOrderDTO.setDisableDiscard(GlobalConsts.NO);

        // 操作者
        createOrderDTO.setOperator("系统");

        // 操作者id
        createOrderDTO.setOperatorId((long) GlobalConsts.OPERATE_USER_TYPE_SYSTEM);

        // 操作者类型
        createOrderDTO.setOperatorType(GlobalConsts.OPERATE_USER_TYPE_CHANNEL);

        // 工单录入方式
        createOrderDTO.setInputType(OrderConsts.ORDER_INPUT_TYPE_API);

        // 城市id
        this.setCityIdBy58DjLocation(createOrderDTO, daoJia58CreateClueParam);

        // 预约时间
        createOrderDTO.setDutyTime(daoJia58CreateClueParam.getBeginTime());

        // 订单金额
        // Double doublePrice = Double.valueOf(daoJia58CreateClueParam.getTotalPrice() * 100);
        // int intPrice = doublePrice.intValue();
        // createOrderDTO.setOriginalAmount(Integer.valueOf(intPrice));

        // 实际支付 和 渠道预付款 均为 用户实际支付金额
        Double doublePrice = Double.valueOf(daoJia58CreateClueParam.getRealPrice() * 100);
        int intPrice = doublePrice.intValue();

        // 只记录大于或等于0的情况
        if (intPrice >= 0) {
            createOrderDTO.setTotalAmount(Integer.valueOf(intPrice));
            createOrderDTO.setChannelPrepayAmount(Integer.valueOf(intPrice));

            // 预付款支付时间
            createOrderDTO.setPrepayTime(daoJia58CreateClueParam.getPayTime());

            // 渠道预付款状态 - 已支付
            createOrderDTO.setChannelPrepayStatus(PayConsts.PAY_STATUS_DONE);
        }

        // 商家补贴
        doublePrice = Double.valueOf(daoJia58CreateClueParam.getCustomSubsidiesPrice() * 100);
        intPrice = doublePrice.intValue();
        if (intPrice > 0) {
            // 暂时没加
        }

        // 产品信息
        this.setProductInfoBy58DjProduct(createOrderDTO, daoJia58CreateClueParam);

        log.info("【{}-API】 创建的的订单信息:[{}]", DaoJia58Consts.CHANNEL_NAME, createOrderDTO.toString());
        return createOrderDTO;
    }

    /**
     * 根据58到家传入的服务和价格信息解析和获得与啄木鸟平台的产品映射信息
     *
     * @param daoJia58CreateClueParam
     * @return DaoJia58MapZmnProduct
     */
    protected DaoJia58MapZmnProduct parseProductMapByDj58CreateClueParam(DaoJia58CreateClueParam daoJia58CreateClueParam) {

        // 获取创建线索中的产品信息
        long dj58ServiceId = daoJia58CreateClueParam.getServiceId();

        // 根据字段“type”去区分，“普通支付订单类型 ”归为“58到家直约”，“信用账户”归为“58同城公寓”
        DaoJia58Consts.ChannelInfo channelInfo = DaoJia58Consts.getChannelInfo(null, daoJia58CreateClueParam.getType());

        // 通过dubbo接口查询配置的产品信息 2021/02/01
        ResponseDTO<List<ProductBaseDRO>> servProductListResponseDTO = channelProductThirdListRemoteService.listByChannelIdAndProductParentIdAndSubId(channelInfo.getId(),
                String.valueOf(dj58ServiceId), null);

        log.info("【{}】 #ChannelProductMapListRemoteService#listByChannelIdAndProductParentIdAndProductSubId# 入参【{}】【{}】，出参【{}】",
                channelInfo.getName(), channelInfo.getId(), dj58ServiceId, servProductListResponseDTO.toString());

        DaoJia58MapZmnProduct daoJia58MapZmnProduct;
        if (!servProductListResponseDTO.isSuccess() || Objects.isNull(servProductListResponseDTO.getData()) ||
                servProductListResponseDTO.getData().isEmpty()) {

            // 查询失败，生成“其他”
            daoJia58MapZmnProduct = DaoJia58MapZmnProduct.builder()
                    .serviceId(dj58ServiceId)
                    .serviceName(daoJia58CreateClueParam.getServiceName())
                    .zmnProductId(OrderConsts.CHANNEL_DISABLED_PRODUCT_ID)
                    .build();
        } else {
            daoJia58MapZmnProduct = DaoJia58MapZmnProduct.builder()
                    .serviceId(dj58ServiceId)
                    .serviceName(daoJia58CreateClueParam.getServiceName())
                    .zmnProductId(servProductListResponseDTO.getData().get(0).getProductId())
                    .build();
        }

        return daoJia58MapZmnProduct;
    }

    /**
     * 根据58到家传入的产品信息填充啄木鸟平台的产品信息
     *
     * @param createOrderDTO
     * @param daoJia58CreateClueParam
     * @return
     */
    protected void setProductInfoBy58DjProduct(CreateOrderDTO createOrderDTO, DaoJia58CreateClueParam daoJia58CreateClueParam) {

        DaoJia58MapZmnProduct daoJia58MapZmnProduct = this.parseProductMapByDj58CreateClueParam(daoJia58CreateClueParam);
        if (Objects.isNull(daoJia58CreateClueParam)) {
            return;
        }

        OrderProductDTO orderProduct = new OrderProductDTO();

        // 10310为后台产品，如果有映射则设置为前端产品
        if (Objects.equals(daoJia58MapZmnProduct.getZmnProductId(),OrderConsts.CHANNEL_DISABLED_PRODUCT_ID)) {
            orderProduct.setProductId(daoJia58MapZmnProduct.getZmnProductId());
            orderProduct.setProductShowType(GlobalConsts.NO);
        } else {
            orderProduct.setShowProductId(daoJia58MapZmnProduct.getZmnProductId());
            orderProduct.setProductShowType(GlobalConsts.YES);
        }

        // 设置产品数量
        if (Objects.nonNull(daoJia58CreateClueParam.getPrices())) {
            orderProduct.setNumber(daoJia58CreateClueParam.getPrices().size());
        } else {
            // xiewenbing 2019.12.02 产品数量为0，APP可能会报错
            orderProduct.setNumber(1);
        }

        List<OrderProductDTO> list = new LinkedList<>();
        list.add(orderProduct);
        createOrderDTO.setOrderProductList(list);
    }

    /**
     * 根据58到家传入的经纬度信息获取城市id
     *
     * @param createOrderDTO
     * @param daoJia58CreateClueParam
     * @return
     */
    protected void setCityIdBy58DjLocation(CreateOrderDTO createOrderDTO, DaoJia58CreateClueParam daoJia58CreateClueParam) {

        // 默认重庆
        Integer cityId = 500100;
        String location = daoJia58CreateClueParam.getLocation();

        do {
            if (Objects.isNull(location) || location.isEmpty()) {
                break;
            }

            String[] splitLocation = location.split(",");
            if (splitLocation.length <= 1) {
                break;
            }

            if (StringUtil.isBlank(splitLocation[0]) || StringUtil.isBlank(splitLocation[1])) {
                break;
            }

            // 获取经纬度
            Double longitude = Double.valueOf(splitLocation[0]);
            Double latitude = Double.valueOf(splitLocation[1]);

            createOrderDTO.setLongitude(longitude);
            createOrderDTO.setLatitude(latitude);

            ResponseDTO<AreaDRO> areaResponse = areaListRemoteService.getAreaByLatAndLng(longitude, latitude);
            AreaDRO areaDRO = areaResponse.getData();
            if (areaDRO != null) {
                cityId = areaDRO.getParentId();
            }
        } while (false);

        createOrderDTO.setCityId(cityId);

        // 记录一下完整地址
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(createOrderDTO.getOperatorLogRemark()).append(" ");
        stringBuilder.append(daoJia58CreateClueParam.getCityName());
        stringBuilder.append(daoJia58CreateClueParam.getAddress());
        createOrderDTO.setOperatorLogRemark(stringBuilder.toString());
    }

    /**
     * 获取58直约到家补充支付的url
     *
     * @param orderId
     * @return String
     * @author xiewenbing
     */
    @Override
    public String getSupplyPayUrl(Long orderId) throws OmsBaseException {
        log.info("获取58直约到家补充支付的URL,订单id为:[{}]", orderId);

        if (Objects.isNull(orderId)) {
            throw new OmsBaseException("错误的订单id");
        }

        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId, orderId);
        if (Objects.isNull(orderWork)) {
            throw new OmsBaseException("找不到对应的订单");
        }

        // 判断外部工单id
        String outerId = orderWork.getOuterId();
        if (Objects.isNull(outerId) || outerId.isEmpty()) {
            throw new OmsBaseException(DaoJia58Consts.ERROR_CODE_SERVER_UNKNOWN, "没有对应的外部订单Id");
        }

        if (orderWork.getChannelId() != DaoJia58Consts.CHANNEL_ID_API) {
            throw new OmsBaseException("订单的渠道不为58到家直约平台");
        }

        // 从58到家直约平台获取价目列表
        OrderExtend orderExtend = orderExtendService.findOrderExtendByOrderId(orderWork.getOrderId());
        if (Objects.isNull(orderExtend)) {
            throw new OmsBaseException(DaoJia58Consts.ERROR_CODE_SERVER_UNKNOWN, "参数错误-查找不到外部订单的扩展数据");
        }

        DaoJia58OrderOuterData orderOutData = JSON.parseObject(orderExtend.getOuterData(), DaoJia58OrderOuterData.class);
        if (Objects.isNull(orderOutData)) {
            throw new OmsBaseException(DaoJia58Consts.ERROR_CODE_SERVER_UNKNOWN, "外部订单保存的数据异常或错误," + orderExtend.getOuterData());
        }

        DaoJia58GetPriceListDTO daoJia58GetPriceListDTO = new DaoJia58GetPriceListDTO();
        daoJia58GetPriceListDTO.setOrderId(Long.valueOf(outerId));
        daoJia58GetPriceListDTO.setCityId(orderOutData.getCityId());
        daoJia58GetPriceListDTO.setServiceId(orderOutData.getServiceId());
        List<DaoJia58PriceItemDTO> daoJia58PriceItemDTOList = sendGetPriceListTo58DaoJia(daoJia58GetPriceListDTO);

        // 查找订单服务项
        List<ZsServiceItemVO> listServiceItem = zsNormalOrderServiceItemBService.findServiceItemVo(orderId, orderId);
        if (Objects.isNull(listServiceItem) || listServiceItem.isEmpty()) {
            throw new OmsBaseException("订单没有找到服务项");
        }

        DaoJia58SupplyPayDTO daoJia58SupplyPayDTO = new DaoJia58SupplyPayDTO();
        daoJia58SupplyPayDTO.setOrderId(Long.parseLong(outerId));
        daoJia58SupplyPayDTO.setType(1);    // 普通支付类型

        List<DaoJia58SupplyPayPriceItem> listSupplyPayPriceItem = Lists.newArrayList();

        // XieWenBing 暂时直接所有服务项都对应为58到家直约的其他
        /**
         double[] otherItemPrice = new double[1];
         boolean[] hasOtherPriceItem = new boolean[1];

         otherItemPrice[0] = 0L;
         hasOtherPriceItem[0] = true;

         listServiceItem.forEach(zsServiceItemVO -> {
         double itemPrice = zsServiceItemVO.getTotalAmount().doubleValue()/100;
         daoJia58SupplyPayDTO.setRealPayMoney(itemPrice + daoJia58SupplyPayDTO.getRealPayMoney());
         otherItemPrice[0] += itemPrice;

         log.info("[{}] 添加服务产品的价格信息，产品id:[{}]，总价为:[{}]",DaoJia58Consts.CHANNEL_NAME,zsServiceItemVO.getProductId(),itemPrice);
         });
         */

        // 根据服务项获取58到家直约平台的价目列表
        double[] otherItemPrice = {0L};
        boolean[] hasOtherPriceItem = {false};

        listServiceItem.forEach(zsServiceItemVO -> {
            List<OrderServiceItem> listOrderServiceItem = zsServiceItemVO.getServiceItemList();
            if (Objects.isNull(listOrderServiceItem) || listOrderServiceItem.isEmpty()) {
                return;
            }

            // 统计金额，并转换为元
            double itemPrice = Optional.ofNullable(zsServiceItemVO.getTotalAmount()).orElse(0).doubleValue() / 100;
            daoJia58SupplyPayDTO.setRealPayMoney(itemPrice + daoJia58SupplyPayDTO.getRealPayMoney());

            listOrderServiceItem.forEach(orderServiceItem -> {
                double serviceItemTotalPrice = Optional.ofNullable(orderServiceItem.getTotalPrice()).orElse(0).doubleValue() / 100;
                log.info("[{}] 根据服务项查找58到家直约平台的服务线价目信息,服务项名称:[{}],服务项Id:[{}]，价格:[{}]", DaoJia58Consts.CHANNEL_NAME, orderServiceItem.getServItemName(),orderServiceItem.getServItemId(), serviceItemTotalPrice);
                Dj58ServicePriceItem dj58ServicePriceItem = dj58ServicePriceItemService.findDj58ServicePriceItemByZmnProductIdAndServiceId(orderServiceItem.getProductId(),orderServiceItem.getServItemId());
                if (Objects.isNull(dj58ServicePriceItem)) {
                    log.info("[{}] 没有对应58到家直约平台的服务线价目信息", DaoJia58Consts.CHANNEL_NAME);

                    hasOtherPriceItem[0] = true;
                    otherItemPrice[0] += serviceItemTotalPrice;
                    return;
                }

                String dj58PriceItemIds = dj58ServicePriceItem.getDj58PriceItemIds();
                if (StringUtils.isEmpty(dj58PriceItemIds)) {
                    return;
                }

                int listIndex = 0;
                for (; listIndex < daoJia58PriceItemDTOList.size(); listIndex++) {
                    if (dj58PriceItemIds.compareTo(daoJia58PriceItemDTOList.get(listIndex).getPriceItemIds()) == 0) {
                        break;
                    }
                }

                if (daoJia58PriceItemDTOList.size() == listIndex) {
                    log.info("[{}] 在58到家直约平台的中没有对应的服务线价目信息", DaoJia58Consts.CHANNEL_NAME);

                    hasOtherPriceItem[0] = true;
                    otherItemPrice[0] += serviceItemTotalPrice;
                    return;
                }

                // 价目列表组合Id列表 XieWenBing
                double serviceItemPrice = Optional.ofNullable(orderServiceItem.getItemPrice()).orElse(0).doubleValue() / 100;
                DaoJia58SupplyPayPriceItem supplyPayPriceItem = new DaoJia58SupplyPayPriceItem();
                supplyPayPriceItem.setNum(orderServiceItem.getNumber());
                supplyPayPriceItem.setPrice(serviceItemPrice);
                supplyPayPriceItem.setPriceItemType(DaoJia58Consts.PRICE_ITEM_TYPE_FIXED);
                supplyPayPriceItem.setPriceItemIds(dj58PriceItemIds);
                listSupplyPayPriceItem.add(supplyPayPriceItem);
            });
        });

        // 如果存在没有对应的价目信息，则计算在一起，统一为其他，价目id为：8000000000
        if (hasOtherPriceItem[0]) {
            log.info("[{}] 添加没有对应的58到家直约平台的服务线价目信息为其他，价格为:[{}]", DaoJia58Consts.CHANNEL_NAME, otherItemPrice[0]);
            DaoJia58SupplyPayPriceItem supplyPayPriceItem = new DaoJia58SupplyPayPriceItem();
            supplyPayPriceItem.setNum(1);
            supplyPayPriceItem.setPrice(otherItemPrice[0]);
            supplyPayPriceItem.setPriceItemType(DaoJia58Consts.PRICE_ITEM_TYPE_CUSTOM);
            supplyPayPriceItem.setPriceItemIds(DaoJia58Consts.OTHER_PRICE_ITEM_IDS);

            listSupplyPayPriceItem.add(supplyPayPriceItem);
        }

        daoJia58SupplyPayDTO.setPriceList(listSupplyPayPriceItem);
        return sendSupplyPayTo58DaoJia(daoJia58SupplyPayDTO);
    }

    /**
     * 获取58到家的access token
     *
     * @param forceGetRemote
     * @return String
     * @author xiewenbing
     */
    private String get58DaoJiaAccessToken(boolean forceGetRemote) {

        // 先从redis里面读取
        if (Objects.nonNull(redisManager) && !forceGetRemote) {
            String accessToken = redisManager.get(RedisKeyConsts.DJ58_REDIS_KEY_ACCESS_TOKEN);
            if (Objects.nonNull(accessToken) && !accessToken.isEmpty()) {
                return accessToken;
            }
        }

        // 发送http请求获取token
        DaoJia58GetTokenDTO daoJia58GetTokenDTO = new DaoJia58GetTokenDTO();

        // 测试代码
        // daoJia58GetTokenDTO.setServiceKey(2232710678L);
        // daoJia58GetTokenDTO.setServiceSecret("cfb4ac2eefd54d2f9c99f4cba0d3560b");

        daoJia58GetTokenDTO.setServiceKey(Long.parseLong(DaoJia58Consts.APPKEY));
        daoJia58GetTokenDTO.setServiceSecret(DaoJia58Consts.SECRET);

        String paramRequest = JSON.toJSONString(daoJia58GetTokenDTO);
        String pathRequest = DaoJia58Consts.GET_TOKERN_PATH;
        DaoJia58Response responseRequest = DaoJia58Util.sendRequstToDaoJia58(pathRequest, paramRequest);
        if (Objects.isNull(responseRequest)) {
            return null;
        }

        // 取得返回的内容
        String dateToken = responseRequest.getData();
        if (Objects.isNull(dateToken) || dateToken.isEmpty()) {
            return null;
        }

        JSONObject jsonObjectResponse = JSON.parseObject(dateToken);
        if (Objects.isNull(jsonObjectResponse)) {
            return null;
        }

        // 解析JSON
        String accessToken = jsonObjectResponse.getString("accessToken");

        // 保存到redis里面
        if (Objects.nonNull(redisManager)) {
            // 设置token有效期为固定的一小时
            redisManager.setex(RedisKeyConsts.DJ58_REDIS_KEY_ACCESS_TOKEN, accessToken, 3600);
        }

        return accessToken;
    }

    /**
     * 同步接收订单给58到家直约服务
     *
     * @param orderWorkLogChange
     * @return
     * @author xiewenbing
     */
    @Override
    public void sendAcceptOrderTo58DaoJia(OrderWorkLogChange orderWorkLogChange) throws OmsBaseException {
        FacadeTracker.FacadeTrackerCore tracker = FacadeTracker.getTracker().remark("同步接单");

        // 参数判断
        if (Objects.isNull(orderWorkLogChange)) {
            throw new OmsBaseException(DaoJia58Consts.ERROR_CODE_PARAM_INVALID, "参数为空");
        }

        // 查看同步记录，对已经同步接单成功的，不需要再次同步
        if (this.findSuccessSyncResult(orderWorkLogChange, OrderStatusConsts.ORDER_STATUS_INPUT)) {
            log.info("【{}-API】 已同步接单，返回", DaoJia58Consts.CHANNEL_NAME);
            tracker.remark("已同步接单，返回");
            return;
        }

        // 判断是否正在发送接收订单的消息，防止重复发送
        if (this.isSyncAcceptOrderTo58(orderWorkLogChange.getOrderId())) {
            log.info("【{}-API】 重复同步接单，返回", DaoJia58Consts.CHANNEL_NAME);
            tracker.remark("重复同步接单，返回");
            return;
        }

        OrderExtend orderExtend = orderExtendService.findOrderExtendByOrderId(orderWorkLogChange.getOrderId());
        Long clueId = 0L;
        Long orgId = 0L;

        if (Objects.isNull(orderExtend)) {

            DaoJia58SyncAcceptOrderData syncAcceptOrderData = getSyncAcceptOrderClueId(orderWorkLogChange.getOrderId());
            if (Objects.isNull(syncAcceptOrderData)) {
                this.addLog(orderWorkLogChange,"数据保存延时，查找不到对应订单数据，同步接单失败");
                throw new OmsBaseException(DaoJia58Consts.ERROR_CODE_SERVER_UNKNOWN, "参数错误-查找不到外部订单的扩展数据");
            }

            clueId = syncAcceptOrderData.getClueId();
            orgId = syncAcceptOrderData.getOrgId();

        } else {

            DaoJia58OrderOuterData orderOutData = JSON.parseObject(orderExtend.getOuterData(), DaoJia58OrderOuterData.class);
            if (Objects.isNull(orderOutData)) {
                throw new OmsBaseException(DaoJia58Consts.ERROR_CODE_SERVER_UNKNOWN, "外部订单保存的数据异常或错误," + orderExtend.getOuterData());
            }

            clueId = Long.parseLong(orderExtend.getExtOuterId());
            orgId = orderOutData.getOrgId();
        }

        DaoJia58AcceptOrderDTO daoJia58AcceptOrderDTO = new DaoJia58AcceptOrderDTO();
        daoJia58AcceptOrderDTO.setType(DaoJia58Consts.DAOJIA58_ACCEPT_ORDER);
        daoJia58AcceptOrderDTO.setThirdOrderId(orderWorkLogChange.getOrderId());
        daoJia58AcceptOrderDTO.setClueId(clueId);
        daoJia58AcceptOrderDTO.setOrgId(orgId);

        // 添加发送请求记录，防止重复发送
        this.setSyncAcceptOrderTo58(orderWorkLogChange.getOrderId(),true);

        // 发送http请求
        String paramJson = JSON.toJSONString(daoJia58AcceptOrderDTO, SerializerFeature.SortField.MapSortField);
        DaoJia58Response responseRequest = sendRequestTo58DaoJia(DaoJia58Consts.ACCEPT_ORDER_PATH, paramJson);

        // 删除发送请求记录，防止重复发送
        this.setSyncAcceptOrderTo58(orderWorkLogChange.getOrderId(),false);

        if (Objects.isNull(responseRequest)) {
            throw new OmsBaseException(DaoJia58Consts.ERROR_CODE_SEND_REQUEST_FAILED, "发送同步接受订单状态消息失败");
        }

        // 取得返回的内容
        String dataResponse = responseRequest.getData();
        if (Objects.isNull(dataResponse) || dataResponse.isEmpty()) {
            throw new OmsBaseException(DaoJia58Consts.ERROR_CODE_PARSE_MSG_FAILED, "获取返回消息内容失败");
        }

        JSONObject jsonObjectResponse = JSON.parseObject(dataResponse);
        if (Objects.isNull(jsonObjectResponse)) {
            throw new OmsBaseException(DaoJia58Consts.ERROR_CODE_PARSE_MSG_FAILED, "解析返回消息内容失败");
        }

        int channelId = orderWorkLogChange.getChannelId();
        if (responseRequest.getCode() == DaoJia58Consts.DAOJIA58_RETURN_CODE_SUCCESS) {
            // 解析JSON，获得58到家直约平台的订单id以及用户电话
            String outerOrderId = jsonObjectResponse.getString("orderId");
            String userMobile = jsonObjectResponse.getString("userMobile");

            log.info("【{}-API】 同步接单成功，渠道订单ID:[{}]，用户电话:[{}]", DaoJia58Consts.CHANNEL_NAME,outerOrderId,userMobile);

            /**
            // 设置订单的第三方id xiewenbing
            OrderQuery updateOrderQuery = new OrderQuery();
            updateOrderQuery.setOuterId(outerOrderId);
            updateOrderQuery.setOrderId(orderWorkLogChange.getOrderId());
            updateOrderQuery.setWorkId(orderWorkLogChange.getWorkId());
            updateOrderQuery.setChannelId(channelId);
            proxyOrderBService.updateChannelOuterId(updateOrderQuery);
            */
            // 设置订单的第三方id以及修改用户电话 xiewenbing
            UpdateOrderDTO updateOrderDTO = new UpdateOrderDTO();
            updateOrderDTO.setOrderId(orderWorkLogChange.getOrderId());
            updateOrderDTO.setOuterId(outerOrderId);
            updateOrderDTO.setPhone(userMobile);

            proxyOrderBService.updateOrder(updateOrderDTO);

            // 保存同步结果
            saveSyncResult(orderWorkLogChange, OrderStatusConsts.ORDER_STATUS_INPUT, responseRequest);

            // 订单开始自动流转
            workFlowContextBService.asyncAutoFlow(orderWorkLogChange.getOrderId(), orderWorkLogChange.getWorkId());

            return;
        }

        // 添加58到家直约平台已取消，删除，或则被接单的线索的处理-取消订单
        if (jsonObjectResponse.containsKey(String.valueOf(DaoJia58Consts.DAOJIA58_RETURN_CODE_NO_CLUE)) ||
                jsonObjectResponse.containsKey(String.valueOf(DaoJia58Consts.DAOJIA58_RETURN_CODE_CLUE_CANCEL)) ||
                jsonObjectResponse.containsKey(String.valueOf(DaoJia58Consts.DAOJIA58_RETURN_CODE_CLUE_OTHER_ACCEPT)) ||
                jsonObjectResponse.containsKey(String.valueOf(DaoJia58Consts.DAOJIA58_RETURN_CODE_CLUE_ACCEPT_FAILED))) {

            // 取消订单
            CancelOrderDTO cancelOrderDTO = new CancelOrderDTO();
            cancelOrderDTO.setOrderId(orderWorkLogChange.getOrderId());
            cancelOrderDTO.setChannelId(channelId);
            cancelOrderDTO.setOperatorId((long) channelId);
            cancelOrderDTO.setOperatorType(GlobalConsts.OPERATE_USER_TYPE_CHANNEL);
            cancelOrderDTO.setRemark(String.format("同步接单信息，但订单对应的线索不存在或被取消，电话 \"%s\" 为假电话，无需回访，无需跟单",OrderConsts.CHANNEL_TEMP_MOBILE));
            proxyOrderBService.cancelOrder(cancelOrderDTO);

            log.info("【{}-API】 同步接单信息失败，错误码;[{}]，取消订单", DaoJia58Consts.CHANNEL_NAME, responseRequest.getCode());
            return;
        }

        throw new OmsBaseException(DaoJia58Consts.ERROR_CODE_SEND_REQUEST_FAILED, "58到家直约平台返回失败");
    }

    /**
     * 同步订单服务开始状态给58到家直约服务
     *
     * @param orderWorkLogChange
     * @return
     * @author xiewenbing
     */
    public void sendBeginServiceTo58DaoJia(OrderWorkLogChange orderWorkLogChange) throws OmsBaseException {
        FacadeTracker.getTracker().remark("同步工程师上门");

        // 参数判断
        if (Objects.isNull(orderWorkLogChange)) {
            throw new OmsBaseException(DaoJia58Consts.ERROR_CODE_PARAM_INVALID, "消息通知参数为空");
        }

        // 获取工单信息
        OrderWork orderWork = orderWorkService.findOrderWorkByKeySrcMaster(orderWorkLogChange.getOrderId(), orderWorkLogChange.getWorkId());
        if (Objects.isNull(orderWork)) {
            throw new OmsBaseException(DaoJia58Consts.ERROR_CODE_SERVER_UNKNOWN, "查不到对应的工单信息");
        }

        String outerId = orderWorkLogChange.getOuterId();
        // 判断外部工单id
        if (Objects.isNull(outerId) || outerId.isEmpty()) {
            throw new OmsBaseException(DaoJia58Consts.ERROR_CODE_SERVER_UNKNOWN, "消息通知参数错误-没有对应的外部订单Id");
        }

        DaoJia58BeginServerDTO daoJia58BeginServerDTO = new DaoJia58BeginServerDTO();
        daoJia58BeginServerDTO.setOrderId(Long.parseLong(outerId));
        daoJia58BeginServerDTO.setRealBeginTime(orderWork.getVisitTime());

        // 发送http请求
        String paramJson = JSON.toJSONString(daoJia58BeginServerDTO, SerializerFeature.SortField.MapSortField);
        DaoJia58Response responseRequest = sendRequestTo58DaoJia(DaoJia58Consts.BEGIN_SERVER_PATH, paramJson);
        if (Objects.isNull(responseRequest) || responseRequest.getCode() != DaoJia58Consts.DAOJIA58_RETURN_CODE_SUCCESS) {
            throw new OmsBaseException(DaoJia58Consts.ERROR_CODE_SEND_REQUEST_FAILED, "发送同步订单服务开始状态消息失败");
        }

        this.saveSyncResult(orderWorkLogChange, OrderStatusConsts.ORDER_STATUS_VISIT, responseRequest);
    }

    /**
     * 发送获取价目列表给58到家直约服务
     *
     * @param daoJia58GetPriceListDTO
     * @return
     * @author xiewenbing
     */
    @Override
    public List<DaoJia58PriceItemDTO> sendGetPriceListTo58DaoJia(DaoJia58GetPriceListDTO daoJia58GetPriceListDTO) throws OmsBaseException {

        // 参数判断
        if (Objects.isNull(daoJia58GetPriceListDTO)) {
            throw new OmsBaseException("参数为空");
        }

        // 发送http请求
        String paramJson = JSON.toJSONString(daoJia58GetPriceListDTO, SerializerFeature.SortField.MapSortField);
        DaoJia58Response responseRequest = sendRequestTo58DaoJia(DaoJia58Consts.GET_PRICE_LIST_PATH, paramJson);
        if (Objects.isNull(responseRequest) || responseRequest.getCode() != DaoJia58Consts.DAOJIA58_RETURN_CODE_SUCCESS) {
            throw new OmsBaseException("发送获取价目列表消息失败");
        }

        // 取得返回的内容
        String dataResponse = responseRequest.getData();
        if (Objects.isNull(dataResponse) || dataResponse.isEmpty()) {
            throw new OmsBaseException("获取返回消息内容失败");
        }

        // 解析JSON，获取补充支付价目列表
        List<DaoJia58PriceItemDTO> listPriceItem = JSON.parseArray(dataResponse, DaoJia58PriceItemDTO.class);
        if (Objects.isNull(listPriceItem)) {
            throw new OmsBaseException("解析返回的节目列表消息内容失败");
        }

        return listPriceItem;
    }

    /**
     * 发送获取补充支付58到家直约服务
     *
     * @param daoJia58SupplyPayDTO
     * @return String
     * @author xiewenbing
     */
    @Override
    public String sendSupplyPayTo58DaoJia(DaoJia58SupplyPayDTO daoJia58SupplyPayDTO) throws OmsBaseException {

        // 参数判断
        if (Objects.isNull(daoJia58SupplyPayDTO)) {
            throw new OmsBaseException("参数为空");
        }

        // 发送http请求
        String paramJson = JSON.toJSONString(daoJia58SupplyPayDTO, SerializerFeature.SortField.MapSortField);
        DaoJia58Response responseRequest = sendRequestTo58DaoJia(DaoJia58Consts.SUPPLY_PAY_PATH, paramJson);
        if (Objects.isNull(responseRequest) || responseRequest.getCode() != DaoJia58Consts.DAOJIA58_RETURN_CODE_SUCCESS) {
            throw new OmsBaseException("发送订单补充支付消息失败");
        }

        // 取得返回的内容
        String dataResponse = responseRequest.getData();
        if (Objects.isNull(dataResponse) || dataResponse.isEmpty()) {
            throw new OmsBaseException("获取返回消息内容失败");
        }

        JSONObject jsonObjectResponse = JSON.parseObject(dataResponse);
        if (Objects.isNull(jsonObjectResponse)) {
            throw new OmsBaseException("解析返回消息内容失败");
        }

        // 解析JSON，获取补充支付url
        String payUrl = jsonObjectResponse.getString("payUrl");

        log.info("获得58直约到家补充支付的URL,支付url为:[{}]", payUrl);

        return payUrl;
    }

    /**
     * 发送获取补充支付58到家直约服务
     *
     * @param orderId
     * @return String
     * @author xiewenbing
     */
    @Override
    public boolean secondPay4apartmentOrder(Long orderId) throws OmsBaseException {
        log.info("【58到家-同城公寓】58到家同城公寓二次支付，orderId=[{}]", orderId);
        try {
            OrderWork dbOrderWork = orderWorkService.findOrderWorkByKey(orderId, orderId);
            if (Objects.isNull(dbOrderWork)) {
                throw new OmsBaseException("找不到对应的订单");
            }
            DaoJia58SupplyPayDTO daoJia58SupplyPayDTO = buildSecondPay4apartmentOrderParams(dbOrderWork);

            // 参数判断
            if (Objects.isNull(daoJia58SupplyPayDTO)) {
                throw new OmsBaseException("参数为空");
            }

            // 发送http请求
            String paramJson = JSON.toJSONString(daoJia58SupplyPayDTO, SerializerFeature.SortField.MapSortField);
            DaoJia58Response responseRequest = sendRequestTo58DaoJia(DaoJia58Consts.SUPPLY_PAY_PATH, paramJson);
            if (Objects.isNull(responseRequest) || responseRequest.getCode() != DaoJia58Consts.DAOJIA58_RETURN_CODE_SUCCESS) {
                throw new OmsBaseException("发送订单补充支付消息失败");
            }

            PayOrderDTO payOrderDTO = new PayOrderDTO();
            payOrderDTO.setOrderPayType(OrderConsts.API_ORDER_PAY_TYPE_CHANNEL_MASTER_AMOUNT);
            payOrderDTO.setChannelId(DaoJia58Consts.CHANNEL_ID_APARTMENT);
            payOrderDTO.setOrderId(dbOrderWork.getOrderId());
            payOrderDTO.setOuterData(JSON.toJSONString(daoJia58SupplyPayDTO));
            payOrderDTO.setWorkId(dbOrderWork.getWorkId());
            payOrderDTO.setPayAmount(MoneyUtil.parseToFen(daoJia58SupplyPayDTO.getRealPayMoney()));
            payOrderDTO.setPayTime(new Date());
            payOrderDTO.setCompleteOrder(true);
            try {
                proxyOrderBService.payOrder(payOrderDTO);
            } catch (Exception e) {
                throw new OmsBaseException(e.getMessage(), e);
            }
            return true;
        } catch (OmsBaseException obe) {
            log.error(String.format("【{}】二次支付失败：", DaoJia58Consts.CHANNEL_NAME_APARTMENT, obe.getMessage()), obe);
            throw obe;
        }
    }

    /**
     * 同步取消订单给58到家直约服务
     *
     * @param orderWorkLogChange
     * @return
     * @author xiewenbing
     */
    @Override
    public void sendCancelOrderTo58DaoJia(OrderWorkLogChange orderWorkLogChange) throws OmsBaseException {
        FacadeTracker.getTracker().remark("同步订单取消");

        // 参数判断
        if (Objects.isNull(orderWorkLogChange)) {
            throw new OmsBaseException(DaoJia58Consts.ERROR_CODE_PARAM_INVALID, "消息通知参数为空");
        }

        // 判断是否为58到家直约平台取消的订单，是则不处理
        if ((orderWorkLogChange.getOperatorId() == DaoJia58Consts.CHANNEL_ID_API) && (orderWorkLogChange.getOperatorType() == GlobalConsts.OPERATE_USER_TYPE_CHANNEL)) {
            return;
        }

        // 获取工单信息
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderWorkLogChange.getOrderId(), orderWorkLogChange.getWorkId());
        if (Objects.isNull(orderWork)) {
            throw new OmsBaseException(DaoJia58Consts.ERROR_CODE_SERVER_UNKNOWN, "查不到对应的工单信息");
        }

        String outerId = orderWorkLogChange.getOuterId();
        // 判断外部工单id
        if (Objects.isNull(outerId) || outerId.isEmpty()) {
            // throw new OmsBaseException(DaoJia58Consts.ERROR_CODE_SERVER_UNKNOWN,"消息通知参数错误-没有对应的外部订单Id");

            // 没有外部工单id，说明没有接单，此时取消，发送拒单
            this.sendRejectOrderTo58DaoJia(orderWorkLogChange.getOrderId());
            return;
        }

        DaoJia58CancelOrderDTO daoJia58CancelOrderDTO = new DaoJia58CancelOrderDTO();
        daoJia58CancelOrderDTO.setOrderId(Long.parseLong(outerId));
        daoJia58CancelOrderDTO.setRealCancelTime(orderWork.getCancelTime());
        daoJia58CancelOrderDTO.setCancelReasonType(DaoJia58Consts.DAOJIA58_ORDER_CANCEL_OTHER);

        // 查找取消原因 xiewenbing 2019.12.06
        String cancelReason = "订单被强制取消";
        OrderRemark orderRemark = orderRemarkService.findByOrderIdAndType(orderWork.getOrderId(), orderWork.getWorkId(), OrderConsts.ORDER_REMARK_TYPE_CANCEL);
        if (orderRemark != null) {
            if (StringUtil.isNotBlank(orderRemark.getContent())) {
                cancelReason = orderRemark.getContent();
            } else {
                List<OrderRemarkDetail> remarkDetailList = orderRemarkDetailService.listOrderRemarkDetailByRemarkId(orderWork.getOrderId(), orderWork.getWorkId(), orderRemark.getRemarkId());
                if (!CollectionUtils.isEmpty(remarkDetailList)) {
                    cancelReason = remarkDetailList.get(0).getMapName();
                }
            }
        }

        daoJia58CancelOrderDTO.setCancelReason(cancelReason);

        /*** xiewenbing 2019.12.20 不进行判断
         // 在取消原因为其他时，需填入取消原因内容
         if (daoJia58CancelOrderDTO.getCancelReasonType() == DaoJia58Consts.DAOJIA58_ORDER_CANCEL_OTHER &&
         (Objects.isNull(daoJia58CancelOrderDTO.getCancelReason()) || daoJia58CancelOrderDTO.getCancelReason().isEmpty())) {
         throw new OmsBaseException("取消原因不能为空");
         }
         */

        String paramJson = JSON.toJSONString(daoJia58CancelOrderDTO, SerializerFeature.SortField.MapSortField);
        DaoJia58Response responseRequest = sendRequestTo58DaoJia(DaoJia58Consts.CANCEL_ORDER_PATH, paramJson);
        if (Objects.isNull(responseRequest) || responseRequest.getCode() != DaoJia58Consts.DAOJIA58_RETURN_CODE_SUCCESS) {
            throw new OmsBaseException(DaoJia58Consts.ERROR_CODE_SEND_REQUEST_FAILED, "同步取消订单消息失败");
        }

        // 取得返回的内容
        String dataResponse = responseRequest.getData();
        if (Objects.nonNull(dataResponse) && !dataResponse.isEmpty()) {
            // 解析JSON，获取违约金额
            JSONObject jsonObjectResponse = JSON.parseObject(dataResponse);
            if (Objects.isNull(jsonObjectResponse)) {
                throw new OmsBaseException(DaoJia58Consts.ERROR_CODE_PARSE_MSG_FAILED, "解析返回消息内容失败");
            }

            // TODO xiewenbing 暂时没有其他处理 2019-11-06
            String defaultMoney = jsonObjectResponse.getString("defaultMoney");
        }

        this.saveSyncResult(orderWorkLogChange, OrderStatusConsts.ORDER_STATUS_CANCEL, responseRequest);
    }

    /**
     * 同步拒接订单给58到家直约服务
     *
     * @param orderId
     * @return
     * @author xiewenbing
     */
    public void sendRejectOrderTo58DaoJia(Long orderId) throws OmsBaseException {

        OrderExtend orderExtend = orderExtendService.findOrderExtendByOrderId(orderId);
        if (Objects.isNull(orderExtend)) {
            throw new OmsBaseException(DaoJia58Consts.ERROR_CODE_SERVER_UNKNOWN, "参数错误-查找不到外部订单的扩展数据");
        }

        DaoJia58OrderOuterData orderOutData = JSON.parseObject(orderExtend.getOuterData(), DaoJia58OrderOuterData.class);
        if (Objects.isNull(orderOutData)) {
            throw new OmsBaseException(DaoJia58Consts.ERROR_CODE_SERVER_UNKNOWN, "外部订单保存的数据异常或错误," + orderExtend.getOuterData());
        }

        log.info("发送拒单消息给58到家直约平台,订单id为:[{}]，线索id为:[{}]", orderId, orderExtend.getExtOuterId());

        DaoJia58AcceptOrderDTO daoJia58AcceptOrderDTO = new DaoJia58AcceptOrderDTO();
        daoJia58AcceptOrderDTO.setType(DaoJia58Consts.DAOJIA58_REJECT_ORDER);
        daoJia58AcceptOrderDTO.setThirdOrderId(orderId);
        daoJia58AcceptOrderDTO.setClueId(Long.parseLong(orderExtend.getExtOuterId()));
        daoJia58AcceptOrderDTO.setOrgId(orderOutData.getOrgId());

        // 发送http请求
        String paramJson = JSON.toJSONString(daoJia58AcceptOrderDTO, SerializerFeature.SortField.MapSortField);
        DaoJia58Response responseRequest = sendRequestTo58DaoJia(DaoJia58Consts.ACCEPT_ORDER_PATH, paramJson);
        if (Objects.isNull(responseRequest)) {
            throw new OmsBaseException(DaoJia58Consts.ERROR_CODE_SEND_REQUEST_FAILED, "发送同步拒接订单状态消息失败");
        }
    }

    /**
     * 同步修改订单给58到家直约服务
     *
     * @param orderWorkLogChange
     * @return
     * @author xiewenbing
     */
    public void sendUpdateOrderTo58DaoJia(OrderWorkLogChange orderWorkLogChange) throws OmsBaseException {
        FacadeTracker.getTracker().remark("同步接单");

        // 参数判断
        if (Objects.isNull(orderWorkLogChange)) {
            throw new OmsBaseException(DaoJia58Consts.ERROR_CODE_PARAM_INVALID, "消息通知参数为空");
        }

        // 获取工单信息
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderWorkLogChange.getOrderId(), orderWorkLogChange.getWorkId());
        if (Objects.isNull(orderWork)) {
            throw new OmsBaseException(DaoJia58Consts.ERROR_CODE_SERVER_UNKNOWN, "查不到对应的工单信息");
        }

        String outerId = orderWorkLogChange.getOuterId();
        // 判断外部工单id
        if (Objects.isNull(outerId) || outerId.isEmpty()) {
            throw new OmsBaseException(DaoJia58Consts.ERROR_CODE_SERVER_UNKNOWN, "消息通知参数错误-没有对应的外部订单Id");
        }

        // 填充信息
        DaoJia58UpdateOrderDTO daoJia58UpdateOrderDTO = new DaoJia58UpdateOrderDTO();
        daoJia58UpdateOrderDTO.setOrderId(Long.parseLong(outerId));
        daoJia58UpdateOrderDTO.setServerName(
                Optional.ofNullable(orderWork.getMasterName())
                        .filter(name -> name.length() >= 1)
                        .map(name -> String.format("%s工程师", name.substring(0,1)))
                        .orElse("工程师")
        );
        daoJia58UpdateOrderDTO.setServerPhone("");
        daoJia58UpdateOrderDTO.setBeginServerTime(orderWork.getDutyTime());

        // 发送http请求
        String paramJson = JSON.toJSONString(daoJia58UpdateOrderDTO, SerializerFeature.SortField.MapSortField);
        DaoJia58Response responseRequest = sendRequestTo58DaoJia(DaoJia58Consts.UPDATE_ORDERP_PATH, paramJson);
        if (Objects.isNull(responseRequest) || responseRequest.getCode() != DaoJia58Consts.DAOJIA58_RETURN_CODE_SUCCESS) {
            throw new OmsBaseException(DaoJia58Consts.ERROR_CODE_SEND_REQUEST_FAILED, "同步修改订单消息失败");
        }

        this.saveSyncResult(orderWorkLogChange, OrderStatusConsts.ORDER_STATUS_DISTRIBUTE, responseRequest);
    }

    /**
     * 同步订单完成给58到家直约服务
     *
     * @param orderWorkLogChange
     * @return
     * @author xiewenbing
     */
    @Override
    public void sendFinishOrderTo58DaoJia(OrderWorkLogChange orderWorkLogChange) throws OmsBaseException {
        FacadeTracker.getTracker().remark("同步订单完成");

        // 参数判断
        if (Objects.isNull(orderWorkLogChange)) {
            throw new OmsBaseException(DaoJia58Consts.ERROR_CODE_PARAM_INVALID, "消息通知参数为空");
        }

        // 获取工单信息
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderWorkLogChange.getOrderId(), orderWorkLogChange.getWorkId());
        if (Objects.isNull(orderWork)) {
            throw new OmsBaseException(DaoJia58Consts.ERROR_CODE_SERVER_UNKNOWN, "查不到对应的工单信息");

        }

        String outerId = orderWorkLogChange.getOuterId();
        // 判断外部工单id
        if (Objects.isNull(outerId) || outerId.isEmpty()) {
            throw new OmsBaseException(DaoJia58Consts.ERROR_CODE_SERVER_UNKNOWN, "消息通知参数错误-没有对应的外部订单Id");
        }

        DaoJia58FinishOrderDTO daoJia58FinishOrderDTO = new DaoJia58FinishOrderDTO();
        daoJia58FinishOrderDTO.setOrderId(Long.parseLong(outerId));
        daoJia58FinishOrderDTO.setRealFinishTime(orderWork.getCompleteTime());

        // 发送http请求
        String paramJson = JSON.toJSONString(daoJia58FinishOrderDTO, SerializerFeature.SortField.MapSortField);
        DaoJia58Response responseRequest = sendRequestTo58DaoJia(DaoJia58Consts.FINISH_ORDER_PATH, paramJson);
        if (Objects.isNull(responseRequest) || responseRequest.getCode() != DaoJia58Consts.DAOJIA58_RETURN_CODE_SUCCESS) {
            throw new OmsBaseException(DaoJia58Consts.ERROR_CODE_SEND_REQUEST_FAILED, "同步订单完成消息失败");
        }

        this.saveSyncResult(orderWorkLogChange, OrderStatusConsts.ORDER_STATUS_COMPLETE, responseRequest);
    }

    /**
     * 发送消息给58到家直约服务
     *
     * @param pathRequest
     * @param paramJson
     * @return DaoJia58Response
     * @author xiewenbing
     */
    @Override
    public DaoJia58Response sendRequestTo58DaoJia(String pathRequest, String paramJson) {

        // 判断参数是否正确
        if (Objects.isNull(pathRequest) || pathRequest.isEmpty() || Objects.isNull(paramJson) || paramJson.isEmpty()) {
            return null;
        }

        DaoJia58SendRequest daoJia58SendRequest = new DaoJia58SendRequest();
        daoJia58SendRequest.setDaojiaJson(JSON.parseObject(paramJson));
        daoJia58SendRequest.setFormat(DaoJia58Consts.DJ58_MSG_FORMAT);
        daoJia58SendRequest.setTimestamp(DaoJia58Util.getTimestamp());
        daoJia58SendRequest.setServiceKey(Long.parseLong(DaoJia58Consts.APPKEY));

        // 测试代码
        // daoJia58SendRequest.setServiceKey(2517907742L);

        // 发送请求
        DaoJia58Response responseRequest = this.sendRequestTo58DaoJia(pathRequest, daoJia58SendRequest);
        if (Objects.isNull(responseRequest)) {
            log.info("【{}-API】 发送请求失败", DaoJia58Consts.CHANNEL_NAME);
            return null;
        }

        return responseRequest;
    }

    /**
     * 发送消息给58到家直约服务
     *
     * @param pathRequest
     * @param daoJia58SendRequest
     * @return DaoJia58Response
     * @author xiewenbing
     */
    private DaoJia58Response sendRequestTo58DaoJia(String pathRequest, DaoJia58SendRequest daoJia58SendRequest) {

        // 参数判断
        if (Objects.isNull(daoJia58SendRequest)) {
            return null;
        }

        int sendTimes = 0;
        boolean getTokenRemote = false;
        DaoJia58Response responseRequest = null;

        // 添加对返回token失效或token不存在的处理
        while (sendTimes < 2) {

            // 测试代码
            // String accessToken = "53ea7944a7b14e088c2b8763c5426842";

            // 获取交互使用的token
            String accessToken = this.get58DaoJiaAccessToken(getTokenRemote);
            if (Objects.isNull(accessToken) || accessToken.isEmpty()) {
                log.info("【{}-API】 获取token失败", DaoJia58Consts.CHANNEL_NAME);
                return null;
            }

            daoJia58SendRequest.setAccessToken(accessToken);

            // 生成签名
            String signRequest = DaoJia58Util.makeRequestSign(daoJia58SendRequest);
            if (Objects.isNull(signRequest) || signRequest.isEmpty()) {
                log.info("【{}-API】 生成签名失败", DaoJia58Consts.CHANNEL_NAME);
                return null;
            }

            daoJia58SendRequest.setSign(signRequest);
            String paramRequest = JSON.toJSONString(daoJia58SendRequest);
            responseRequest = DaoJia58Util.sendRequstToDaoJia58(pathRequest, paramRequest);
            if (Objects.isNull(responseRequest)) {
                return null;
            }

            switch (responseRequest.getCode()) {
                // token 失效或异常
                case DaoJia58Consts.DAOJIA58_RETURN_CODE_TOKEN_ERROR:
                    getTokenRemote = true;
                    break;
                default:
                    return responseRequest;
            }

            sendTimes++;
        }

        return responseRequest;
    }

    /**
     * 保存状态同步结果信息
     *
     * @param orderWorkLogChange
     * @param orderStatus
     * @param result
     */
    @SuppressWarnings("all")
    private void saveSyncResult(OrderWorkLogChange orderWorkLogChange, int orderStatus, DaoJia58Response result) {
        if (Objects.isNull(result) || Objects.isNull(orderWorkLogChange)) {
            return;
        }

        OrderNotifyLog orderNotifyLog = new OrderNotifyLog();
        orderNotifyLog.setMqMsgKey(orderWorkLogChange.getMqMsgKey());
        orderNotifyLog.setOrderId(orderWorkLogChange.getOrderId());
        orderNotifyLog.setChannelId(orderWorkLogChange.getChannelId());
        orderNotifyLog.setOrderStatus(orderWorkLogChange.getStatus());
        orderNotifyLog.setOrderResultStatus(orderWorkLogChange.getResultStatus());
        orderNotifyLog.setNotifyStatus(String.valueOf(orderStatus));
        orderNotifyLog.setType(OrderConsts.ORDER_NOTIFY_TYPE_CHANGE);
        orderNotifyLog.setNotifyTime(DateUtil.getNow());
        orderNotifyLog.setNotifyResultMsg(String.format("[%s]-%s",
                OrderStatusConsts.getOrderStatusName(orderStatus), result.getMessage()));

        ResultDTO resultDTO = new ResultDTO();
        resultDTO.setStatus(result.getCode() == DaoJia58Consts.ZMN_RETURN_CODE_SUCCESS ? StatusConsts.STATUS_SUCCESS : StatusConsts.STATUS_ERROR);
        resultDTO.setData(orderNotifyLog);

        orderNotifyLogBService.saveNotifyLog(resultDTO);
    }

    /**
     * 查询状态同步结果信息
     *
     * @param orderWorkLogChange
     * @param orderStatus
     * @return boolean
     */
    private Boolean findSuccessSyncResult(OrderWorkLogChange orderWorkLogChange, int orderStatus) {
        Long orderId = orderWorkLogChange.getOrderId();
        List<OrderNotifyLog> orderNotifyLogs = orderNotifyLogBService.listByOrderId(orderId);
        if (Objects.isNull(orderNotifyLogs)) {
            return Boolean.FALSE;
        }

        for (OrderNotifyLog item : orderNotifyLogs) {
            if (Objects.equals(String.valueOf(orderStatus), item.getNotifyStatus())
                    && Objects.equals(StatusConsts.STATUS_SUCCESS, item.getNotifyResultStatus())) {
                return Boolean.TRUE;
            }
        }

        return Boolean.FALSE;
    }

    /**
     * 向师傅APP端推送消息支付成功消息
     * @param payOrderDTO
     */
    private void pushPayMessage(PayOrderDTO payOrderDTO) {

        // 支付成功消息push推送
        Map<String, Object> params = Maps.newHashMap();
        OrderWork dbOrderWork = orderWorkService.findOrderWorkByKey(payOrderDTO.getOrderId(), payOrderDTO.getWorkId());
        params.put("order_id", String.valueOf(dbOrderWork.getOrderId()));
        params.put("work_id", String.valueOf(dbOrderWork.getWorkId()));
        params.put("amount", String.valueOf(AmountUtil.fen2Yuan(payOrderDTO.getPayAmount()).doubleValue()));
        messageSendAppService.pushAppMessageInfo(MessageRuleIdConsts.PUSH_MSG_RULEID_ORDER_PAY,JSON.toJSONString(params),dbOrderWork);
    }

    /**
     * 准备“58到家-同城公寓”二次支付接口需要的参数
     *      啄木鸟调“发起补充支付“接口同步补尾款金额至58（注：58返回成功即为默认支付成功，工程师收款额即为渠道代收金额）
     * 		啄木鸟发起完成：啄木鸟调“同步订单完成“接口同步完成至58（以调取支付链接返回成功为节点工单状态置为已完成）
     *
     * @param orderWork
     * @return String
     * @author lhl
     */
    public DaoJia58SupplyPayDTO buildSecondPay4apartmentOrderParams(OrderWork orderWork) throws OmsBaseException {
        String outerId = null;
        Integer masterAmount = null;
        // 查询出订单，并获取外部订单号
        {
            // 判断外部工单id
            outerId = orderWork.getOuterId();
            if (Objects.isNull(outerId) || outerId.isEmpty()) {
                throw new OmsBaseException(DaoJia58Consts.ERROR_CODE_SERVER_UNKNOWN, "没有对应的外部订单Id");
            }

            if (orderWork.getChannelId() != DaoJia58Consts.CHANNEL_ID_APARTMENT) {
                throw new OmsBaseException("订单的渠道不为58到家-同城公寓平台");
            }

            masterAmount = orderWork.getMasterAmount();
            if (masterAmount == null || masterAmount.intValue() <= 0) {
                throw new OmsBaseException("订单不存在师傅收款额");
            }
        }

        DaoJia58SupplyPayDTO daoJia58SupplyPayDTO = new DaoJia58SupplyPayDTO();
        daoJia58SupplyPayDTO.setOrderId(Long.parseLong(outerId));
        daoJia58SupplyPayDTO.setType(2);    // 信用支付类型

        double otherItemPrice = MoneyUtil.parseToYuan(masterAmount);
        daoJia58SupplyPayDTO.setRealPayMoney(otherItemPrice);

        DaoJia58SupplyPayPriceItem supplyPayPriceItem = new DaoJia58SupplyPayPriceItem();
        supplyPayPriceItem.setNum(1);
        supplyPayPriceItem.setPrice(otherItemPrice);
        supplyPayPriceItem.setPriceItemType(DaoJia58Consts.PRICE_ITEM_TYPE_CUSTOM);
        supplyPayPriceItem.setPriceItemIds(DaoJia58Consts.OTHER_PRICE_ITEM_IDS);
        daoJia58SupplyPayDTO.setPriceList(Lists.newArrayList(supplyPayPriceItem));

/*        // 从58到家平台获取价目列表,并构建成查找器
        Map<String, DaoJia58PriceItemDTO> dj58PriceItemFinder = null;
        {
            OrderExtend orderExtend = orderExtendService.findOrderExtendByOrderId(orderWork.getOrderId());
            if (Objects.isNull(orderExtend)) {
                throw new OmsBaseException(DaoJia58Consts.ERROR_CODE_SERVER_UNKNOWN, "参数错误-查找不到外部订单的扩展数据");
            }

            DaoJia58OrderOuterData orderOutData = JSON.parseObject(orderExtend.getOuterData(), DaoJia58OrderOuterData.class);
            if (Objects.isNull(orderOutData)) {
                throw new OmsBaseException(DaoJia58Consts.ERROR_CODE_SERVER_UNKNOWN, "外部订单保存的数据异常或错误," + orderExtend.getOuterData());
            }

            DaoJia58GetPriceListDTO daoJia58GetPriceListDTO = new DaoJia58GetPriceListDTO();
            daoJia58GetPriceListDTO.setOrderId(Long.valueOf(outerId));
            daoJia58GetPriceListDTO.setCityId(orderOutData.getCityId());
            daoJia58GetPriceListDTO.setServiceId(orderOutData.getServiceId());
            List<DaoJia58PriceItemDTO> daoJia58PriceItemDTOList = sendGetPriceListTo58DaoJia(daoJia58GetPriceListDTO);

            int mapSize = CollectionUtils.isEmpty(daoJia58PriceItemDTOList) ? 0 : daoJia58PriceItemDTOList.size() * 2;
            dj58PriceItemFinder = new HashMap<>(mapSize);
            for (DaoJia58PriceItemDTO item : daoJia58PriceItemDTOList) {
                dj58PriceItemFinder.put(item.getPriceItemIds(), item);
            }
        }

        // 查找订单服务项
        List<ZsServiceItemVO> serviceItemVOlist = zsNormalOrderServiceItemBService.findServiceItemVo(orderId, orderId);
        if (Objects.isNull(serviceItemVOlist) || serviceItemVOlist.isEmpty()) {
            throw new OmsBaseException("订单没有找到服务项");
        }

        int tatalPrice = 0;
        List<DaoJia58SupplyPayPriceItem> listSupplyPayPriceItem = Lists.newArrayList();

        // 根据服务项获取58到家平台的价目列表
        boolean hasOtherPriceItem = false;
        int otherItemPrice = 0;

        for (ZsServiceItemVO itemVO : serviceItemVOlist) {
            List<OrderServiceItem> zmnOrderServiceItems = itemVO.getServiceItemList();
            if (Objects.isNull(zmnOrderServiceItems) || zmnOrderServiceItems.isEmpty()) {
                continue;
            }

            // 统计金额，并转换为元
            tatalPrice += Optional.ofNullable(itemVO.getTotalAmount()).orElse(0);

            for (OrderServiceItem item : zmnOrderServiceItems) {
                Dj58ServicePriceItem dj58ServicePriceItem = dj58ServicePriceItemService
                        .findDj58ServicePriceItemByZmnServiceId(item.getServItemId());

                if (Objects.isNull(dj58ServicePriceItem)) {
                    log.info("【{}】没有对应58到家平台的服务线价目信息：serviceItemId=[{}]",
                            DaoJia58Consts.CHANNEL_NAME_APARTMENT, item.getServItemId());

                    hasOtherPriceItem = true;
                    otherItemPrice += Optional.ofNullable(item.getTotalPrice()).orElse(0);
                    continue;
                }

                String dj58PriceItemIds = dj58ServicePriceItem.getDj58PriceItemIds();
                if (StringUtils.isEmpty(dj58PriceItemIds)) {
                    continue;
                }

                DaoJia58PriceItemDTO daoJia58PriceItemDTO = dj58PriceItemFinder.get(dj58PriceItemIds);
                if (Objects.isNull(daoJia58PriceItemDTO)) {
                    log.info("【{}】没有对应58到家平台的服务线价目信息：serviceItemId=[{}]",
                            DaoJia58Consts.CHANNEL_NAME_APARTMENT, item.getServItemId());

                    hasOtherPriceItem = true;
                    otherItemPrice += Optional.ofNullable(item.getTotalPrice()).orElse(0);
                    continue;
                }

                // 价目列表组合Id列表 XieWenBing
                DaoJia58SupplyPayPriceItem supplyPayPriceItem = new DaoJia58SupplyPayPriceItem();
                supplyPayPriceItem.setNum(item.getNumber());
                int serviceItemPrice = Optional.ofNullable(item.getItemPrice()).orElse(0);
                supplyPayPriceItem.setPrice(MoneyUtil.parseToYuan(serviceItemPrice));
                supplyPayPriceItem.setPriceItemType(DaoJia58Consts.PRICE_ITEM_TYPE_FIXED);
                supplyPayPriceItem.setPriceItemIds(dj58PriceItemIds);
                listSupplyPayPriceItem.add(supplyPayPriceItem);
            }

            // 如果存在没有对应的价目信息，则计算在一起，统一为其他，价目id为：8000000000
            if (hasOtherPriceItem) {
                log.info("【{}】添加没有对应的58到家直约平台的服务线价目信息为其他，价格为:[{}]",
                        DaoJia58Consts.CHANNEL_NAME_APARTMENT, MoneyUtil.parseToYuanStr(otherItemPrice));

                DaoJia58SupplyPayPriceItem supplyPayPriceItem = new DaoJia58SupplyPayPriceItem();
                supplyPayPriceItem.setNum(1);
                supplyPayPriceItem.setPrice(MoneyUtil.parseToYuan(otherItemPrice));
                supplyPayPriceItem.setPriceItemType(DaoJia58Consts.PRICE_ITEM_TYPE_CUSTOM);
                supplyPayPriceItem.setPriceItemIds(DaoJia58Consts.OTHER_PRICE_ITEM_IDS);

                listSupplyPayPriceItem.add(supplyPayPriceItem);
            }
        }

        DaoJia58SupplyPayDTO daoJia58SupplyPayDTO = new DaoJia58SupplyPayDTO();
        daoJia58SupplyPayDTO.setOrderId(Long.parseLong(outerId));
        daoJia58SupplyPayDTO.setType(2);    // 信用支付类型
        daoJia58SupplyPayDTO.setRealPayMoney(MoneyUtil.parseToYuan(tatalPrice));
        daoJia58SupplyPayDTO.setPriceList(listSupplyPayPriceItem);*/

        return daoJia58SupplyPayDTO;
    }


    /**
     *  读取redis，判断是否在同步接单状态中
     *
     * @param orderId
     * @return
     */
    private boolean isSyncAcceptOrderTo58(Long orderId) {

        if (Objects.isNull(redisManager)) {
            return false;
        }

        String redisKey = String.format("%s_%d",RedisKeyConsts.DJ58_REDIS_KEY_ACCPET_ORDER,orderId);
        DaoJia58SyncAcceptOrderData syncAcceptOrderData = null;
        String redisValue = redisManager.get(redisKey);
        if (StringUtils.isEmpty(redisValue)) {
            return false;
        }

        try {
            syncAcceptOrderData = JSON.parseObject(redisValue,DaoJia58SyncAcceptOrderData.class);
            return Objects.isNull(syncAcceptOrderData) ? false : syncAcceptOrderData.getSyncAccept();
        } catch (Exception e) {
            log.info("【{}】解析同步接单redis缓存数据异常",DaoJia58Consts.CHANNEL_NAME);
        }

        return redisValue.compareTo("1") == 0 ? true : false;
    }

    /**
     * 设置订单是否同步接单状态中
     *
     * @param orderId 订单id
     * @param syncAcceptOrder  是否再同步接单
     */
    private void setSyncAcceptOrderTo58(Long orderId,boolean syncAcceptOrder) {

        if (Objects.isNull(redisManager)) {
            return;
        }

        String redisKey = String.format("%s_%d",RedisKeyConsts.DJ58_REDIS_KEY_ACCPET_ORDER,orderId);
        DaoJia58SyncAcceptOrderData syncAcceptOrderData = null;
        String redisValue = redisManager.get(redisKey);

        if (!StringUtils.isEmpty(redisValue)) {
            try {
                syncAcceptOrderData = JSON.parseObject(redisValue,DaoJia58SyncAcceptOrderData.class);
            } catch (Exception e) {
                log.info("【{}】解析同步接单redis缓存数据异常",DaoJia58Consts.CHANNEL_NAME);
            }
        }

        if (Objects.isNull(syncAcceptOrderData)) {
            syncAcceptOrderData = new DaoJia58SyncAcceptOrderData();
        }

        syncAcceptOrderData.setSyncAccept(syncAcceptOrder);
        redisManager.setex(redisKey,JSON.toJSONString(syncAcceptOrderData),3600);
    }

    /**
     * 保存线索id到redis缓存
     * @param orderId
     * @param clueId
     */
    private void saveSyncAcceptOrderClueId(Long orderId,Long clueId,Long orgId) {

        if (Objects.isNull(redisManager)) {
            return;
        }

        String redisKey = String.format("%s_%d",RedisKeyConsts.DJ58_REDIS_KEY_ACCPET_ORDER,orderId);
        DaoJia58SyncAcceptOrderData syncAcceptOrderData = new DaoJia58SyncAcceptOrderData();
        syncAcceptOrderData.setClueId(clueId);
        syncAcceptOrderData.setOrgId(orgId);
        syncAcceptOrderData.setSyncAccept(Boolean.FALSE);

        redisManager.setex(redisKey,JSON.toJSONString(syncAcceptOrderData),3600);
    }

    /**
     * 从 redis读取线索id
     * @param orderId
     * @return
     */
    private DaoJia58SyncAcceptOrderData getSyncAcceptOrderClueId(Long orderId) {

        if (Objects.isNull(redisManager)) {
            return null;
        }

        String redisKey = String.format("%s_%d",RedisKeyConsts.DJ58_REDIS_KEY_ACCPET_ORDER,orderId);
        String redisValue = redisManager.get(redisKey);
        if (StringUtils.isEmpty(redisValue)) {
            return null;
        }

        try {
            return JSON.parseObject(redisValue,DaoJia58SyncAcceptOrderData.class);
        } catch (Exception e) {
            log.info("【{}】解析同步接单redis缓存数据异常",DaoJia58Consts.CHANNEL_NAME);
        }

        return null;
    }

    /**
     * 人工同步订单状态给58
     * @param syncOrderStateDTO
     * @return
     * @throws OmsBaseException
     */
    public ResultDTO syncOrderState(DaoJia58SyncOrderStateDTO syncOrderStateDTO) throws OmsBaseException {

        if (Objects.isNull(syncOrderStateDTO)) {
            throw new OmsBaseException("参数不能为空");
        }

        if (NumberUtil.isNullOrZero(syncOrderStateDTO.getOrderId()) || StringUtils.isEmpty(syncOrderStateDTO.getOrderId())) {
            throw new OmsBaseException("参数不正确--订单id或外部订单id为空");
        }

        Long orderId = syncOrderStateDTO.getOrderId();
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId,orderId);
        if (Objects.isNull(orderWork)) {
            throw new OmsBaseException("参数错误--查找不到对应订单");
        }

        if (orderWork.getInputType() != OrderConsts.ORDER_INPUT_TYPE_API) {
            throw new OmsBaseException("参数错误--订单录入类型不为API");
        }

        if (!Objects.equals(orderWork.getOuterId(),syncOrderStateDTO.getOuterId())) {
            throw new OmsBaseException("参数错误--外部订单id不匹配");
        }

        if (orderWork.getChannelId() != DaoJia58Consts.CHANNEL_ID_API &&
                orderWork.getChannelId() != DaoJia58Consts.CHANNEL_ID_APARTMENT &&
                orderWork.getChannelId() != DaoJia58Consts.CHANNEL_ID_DJ58_REWORK  ) {
            throw new OmsBaseException("参数错误--订单渠道不为58到家");
        }

        int state = syncOrderStateDTO.getOrderState().intValue();

        log.info("【{}】人工同步订单状态，【{}】【{}】【{}】",DaoJia58Consts.CHANNEL_NAME,orderId,syncOrderStateDTO.getOuterId(),syncOrderStateDTO.getOrderState());
        OrderWorkLogChange orderWorkLogChange = new OrderWorkLogChange();
        orderWorkLogChange.setOrderId(orderId);
        orderWorkLogChange.setWorkId(orderId);
        orderWorkLogChange.setChannelId(orderWork.getChannelId());
        orderWorkLogChange.setOuterId(orderWork.getOuterId());
        orderWorkLogChange.setStatus(orderWork.getStatus());
        orderWorkLogChange.setResultStatus(orderWork.getResultStatus());
        orderWorkLogChange.setOperatorId((long)GlobalConsts.OPERATE_USER_TYPE_SYSTEM);
        orderWorkLogChange.setOperatorType(GlobalConsts.OPERATE_USER_TYPE_SYSTEM);

        switch (state) {
            // 接单
            case OrderLogConsts.ORDER_LOG_TYPE_CONFIRM:
                if (orderWork.getStatus() < OrderStatusConsts.ORDER_STATUS_CONFIRM) {
                    throw new OmsBaseException("参数错误--订单不能同步该状态");
                }

                sendAcceptOrderTo58DaoJia(orderWorkLogChange);
                break;
            // 派单
            case OrderLogConsts.ORDER_LOG_TYPE_DISTRIBUTE:
                if (orderWork.getStatus() < OrderStatusConsts.ORDER_STATUS_DISTRIBUTE) {
                    throw new OmsBaseException("参数错误--订单不能同步该状态");
                }

                sendUpdateOrderTo58DaoJia(orderWorkLogChange);
                break;
            // 工程师上门
            case OrderLogConsts.ORDER_LOG_TYPE_VISIT:
                if (orderWork.getStatus() < OrderStatusConsts.ORDER_STATUS_VISIT) {
                    throw new OmsBaseException("参数错误--订单不能同步该状态");
                }

                sendBeginServiceTo58DaoJia(orderWorkLogChange);
                break;
            //  取消
            case OrderLogConsts.ORDER_LOG_TYPE_CANCEL:
                if (orderWork.getResultStatus() < OrderStatusConsts.WORK_RESULT_FAIL) {
                    throw new OmsBaseException("参数错误--订单不能同步该状态");
                }

                sendCancelOrderTo58DaoJia(orderWorkLogChange);
                break;
            default:
                throw new OmsBaseException("参数错误--状态不应同步");

        }

        return ResultDTO.success("OK");
    }

    /**
     *  添加日志记录
     * @param orderWork
     * @param errLog
     * @throws OmsBaseException
     */
    private void addLog(OrderWork orderWork,String errLog) throws OmsBaseException {

        OrderLogDTO orderLogDTO = new OrderLogDTO();
        orderLogDTO.setOrderId(orderWork.getOrderId());
        orderLogDTO.setOuterId(orderWork.getOuterId());
        orderLogDTO.setChannelId(orderWork.getChannelId());
        orderLogDTO.setOperatorId((long)orderWork.getChannelId());
        orderLogDTO.setOperatorType(GlobalConsts.OPERATE_USER_TYPE_CHANNEL);
        orderLogDTO.setType(OrderLogConsts.ORDER_LOG_TYPE_CHANNEL_REMARK);
        orderLogDTO.setOperatorLogRemark(errLog);

        proxyOrderBService.addOrderLog(orderLogDTO);
    }

    /**
     *  添加日志记录
     * @param orderWorkLogChange
     * @param errLog
     * @throws OmsBaseException
     */
    private void addLog(OrderWorkLogChange orderWorkLogChange,String errLog) throws OmsBaseException {

        OrderLogDTO orderLogDTO = new OrderLogDTO();
        orderLogDTO.setOrderId(orderWorkLogChange.getOrderId());
        orderLogDTO.setOuterId(orderWorkLogChange.getOuterId());
        orderLogDTO.setChannelId(orderWorkLogChange.getChannelId());
        orderLogDTO.setOperatorId((long)orderWorkLogChange.getChannelId());
        orderLogDTO.setOperatorType(GlobalConsts.OPERATE_USER_TYPE_CHANNEL);
        orderLogDTO.setType(OrderLogConsts.ORDER_LOG_TYPE_CHANNEL_REMARK);
        orderLogDTO.setOperatorLogRemark(errLog);

        proxyOrderBService.addOrderLog(orderLogDTO);
    }
}
